// -*- C++ -*- generated by wxGlade 0.6.3 on Thu Mar  5 10:11:10 2009
/*
  Copyright 2009 Ronald S. Burkey <info@sandroid.org>
  This file is part of yaAGC.

  yaAGC 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.

  yaAGC 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.

  You should have received a copy of the GNU General Public License
  along with yaAGC; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Filename:	VirtualAGC.cpp
  Purpose:	This file contains the GUI event handlers for VirtualAGC.
  		The purpose of VirtualAGC is to provide a cross-platform
		GUI front-end that can be used to start up a Virtual AGC
		simulation (yaAGC, yaDSKY, yaAGS, etc.) in a convenient
		way.
  Mods:		2009-03-02 RSB	Began.
  		2009-03-08 RSB	Getting close.
		2009-03-11 RSB	Added yaTelemetry, bypassing the workaround
				in which yaDSKY provided this service.
		2009-03-12 RSB	Now yaAGC and yaAGS load the symbol tables
				only if in --debug mode.  The tables are
				*big*, and on some platforms with limited
				memory the insistance on always loading them
				could cause yaAGC to run out of RAM and 
				thus to abort at startup.
		2009-03-13 RSB	Added provision for different telemetry-screen
				types.
		2009-03-15 RSB	Added the Validation Suite simulation type.
				Added source-view buttons.
		2009-03-17 RSB	Can now show script contents from the 
				run-simulation window.
		2009-03-23 RSB	Began adding digital-upload stuff.
		2009-03-24 RSB	That appears to work now.
		2009-03-25 RSB	Added custom AGC core-dump files.
		2009-03-26 RSB	Added shellouts for the Digital Uplink.
		2009-03-28 RSB	Replaced yaACA with yaACA3.
		2009-04-05 RSB	Tweaked the getting of the path to the
				executables to make it work properly in
				FreeBSD.
		2009-04-06 RSB	Now use yaACA3 *or* yaACA, depending on
				which one the configuration file is 
				found for.
   
  This file is partially generated by wxGlade from VirtualAGC.wxg.
  (Of course, I wrote VirtualAGC.wxg and there's no way to embed any
  copyright or licensing info in it, but I assert the same copyright
  and licensing for it as for this file.  Conversely, even though 
  this file is partially machine-generated, it is generated from 
  my instructions in VirtualAGC.wxg, so I can assert copyright.)  
  However, this section of the file is not overwritten, and is 
  maintained manually.
*/

#include <stdio.h>
#include <errno.h>
#include <ctype.h>

#include "wx/file.h"
#include "wx/textfile.h"
#include "wx/stdpaths.h"
#include "wx/filefn.h"
#include "wx/utils.h"

#include "VirtualAGC.h"
#include "../yaAGC/yaAGC.h"
#include "../yaAGC/agc_engine.h"

// This is the array where shell commands for the Digital Uplink
// are stored.
#define MAX_SHELLOUTS 1024
static char *UplinkShellouts[MAX_SHELLOUTS];
static int NumShellouts = 0, OnShellout = 0;

#ifdef WIN32
#define EOL "\r\n"
#define PATH_DELIMITER '\\'
#define RESOURCE_PATH
#else
#define EOL "\n"
#define PATH_DELIMITER '/'
#endif

#define SET_FONT(Object,Relative) \
  Font = Object->GetFont (); \
  Font.SetPointSize (Points + Relative); \
  Object->SetFont (Font)

#define SCALE_BITMAP(Object) \
  Size = Object->GetSize (); \
  Height = (Size.GetHeight () * Points) / StartingPoints; \
  Width = (Size.GetWidth () * Points) / StartingPoints; \
  Image = Bitmap.ConvertToImage (); \
  Image.Rescale (Width, Height); \
  Bitmap = wxBitmap (Image); \
  Object->SetBitmap (Bitmap)

void
VirtualAGC::SetSize (void)
{
  wxFont Font;
  wxBitmap Bitmap;
  wxImage Image;
  wxSize Size;
  int Width, Height;
  SET_FONT (SimTypeLabel, 2);
  //SET_FONT (AgcFilenameLabel, 0);
  SET_FONT (AgcCustomFilename, 0);
  SET_FONT (DeviceListLabel, 2);
  //SET_FONT (AeaFilenameLabel, 0);
  SET_FONT (AeaCustomFilename, 0);
  SET_FONT (OptionList, 2);
  SET_FONT (Apollo7CmButton, 0);
  SET_FONT (Colossus249Button, 0);
  SET_FONT (Apollo9CmButton, 0);
  SET_FONT (Apollo9LmButton, 0);
  SET_FONT (Apollo10CmButton, 0);
  SET_FONT (Apollo10LmButton, 0);
  SET_FONT (Comanche55Button, 0);
  SET_FONT (Luminary99Button, 0);
  SET_FONT (Apollo12CmButton, 0);
  SET_FONT (Apollo12LmButton, 0);
  SET_FONT (Apollo13CmButton, 0);
  SET_FONT (Luminary131Button, 0);
  SET_FONT (Apollo14CmButton, 0);
  SET_FONT (Apollo14LmButton, 0);
  SET_FONT (Artemis72Button, 0);
  SET_FONT (Apollo15LmButton, 0);
  SET_FONT (AgcCustomButton, 0);
  SET_FONT (DeviceAgcCheckbox, 0);
  SET_FONT (DeviceDskyCheckbox, 0);
  SET_FONT (DeviceAcaCheckbox, 0);
  SET_FONT (DeviceTelemetryCheckbox, 0);
  SET_FONT (DeviceAeaCheckbox, 0);
  SET_FONT (DeviceDedaCheckbox, 0);
  SET_FONT (DeviceCpumonCheckbox, 0);
  SET_FONT (DeviceImuCheckbox, 0);
  SET_FONT (DeviceDiscoutCheckbox, 0);
  SET_FONT (DeviceCrewinCheckbox, 0);
  SET_FONT (DeviceSysinCheckbox, 0);
  SET_FONT (DevicePropulsionCheckbox, 0);
  SET_FONT (NoviceButton, 0);
  SET_FONT (ExpertButton, 0);
  SET_FONT (FlightProgram4Button, 0);
  SET_FONT (FlightProgram5Button, 0);
  SET_FONT (FlightProgram6Button, 0);
  SET_FONT (FlightProgram7Button, 0);
  SET_FONT (FlightProgram8Button, 0);
  SET_FONT (AeaCustomButton, 0);
  SET_FONT (StartupWipeButton, 0);
  SET_FONT (StartupPreserveButton, 0);
  SET_FONT (StartupResumeButton, 0);
  SET_FONT (CustomResumeButton, 0);
  SET_FONT (CoreFilename, 0);
  SET_FONT (CoreBrowse, 0);
  SET_FONT (CoreSaveButton, 0);
  SET_FONT (DskyFullButton, 0);
  SET_FONT (DskyHalfButton, 0);
  SET_FONT (DskyLiteButton, 0);
  SET_FONT (TelemetryResizable, 0);
  SET_FONT (TelemetryRetro, 0);
  SET_FONT (AgcDebugNormalButton, 0);
  SET_FONT (AgcDebugMonitorButton, 0);
  SET_FONT (DedaFullButton, 0);
  SET_FONT (DedaHalfButton, 0);
  SET_FONT (AeaDebugNormalButton, 0);
  SET_FONT (AeaDebugMonitorButton, 0);
  SET_FONT (RunButton, 0);
  SET_FONT (DefaultsButton, 0);
  SET_FONT (ExitButton, 0);
#if 0
  if (Points != StartingPoints)
    {
      SCALE_BITMAP (PatchBitmap);
      SCALE_BITMAP (Patch1Bitmap);
      SCALE_BITMAP (Patch7Bitmap);
      SCALE_BITMAP (Patch8Bitmap);
      SCALE_BITMAP (Patch9Bitmap);
      SCALE_BITMAP (Patch10Bitmap);
      SCALE_BITMAP (Patch11Bitmap);
      SCALE_BITMAP (Patch12Bitmap);
      SCALE_BITMAP (Patch13Bitmap);
      SCALE_BITMAP (Patch14Bitmap);
      SCALE_BITMAP (Patch15Bitmap);
      SCALE_BITMAP (Patch16Bitmap);
      SCALE_BITMAP (Patch17Bitmap);
    }
#endif
}


// begin wxGlade: ::extracode
// end wxGlade



VirtualAGC::VirtualAGC(wxWindow* parent, int id, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
    wxFrame(parent, id, title, pos, size, wxCAPTION|wxMINIMIZE_BOX|wxCLOSE_BOX|wxCLIP_CHILDREN|wxSYSTEM_MENU)
{
    wxStandardPaths StandardPaths;

    // We auto-adjust fonts and image sizes if the screen size is too small.
    wxFont Font = GetFont ();
    StartingPoints = Font.GetPointSize ();
    Points = StartingPoints;
    int x, y, height, width;
    wxClientDisplayRect (&x, &y, &width, &height);
    ReallySmall = 0;
    if (height < 768)
      {
        Points = StartingPoints - 4;
	ReallySmall = 1;
      }
    else if (height < 1024)
      {
        Points = StartingPoints - 2;
	ReallySmall = 1;
      }
    if (Points < 8)
      Points = 8;
    Font.SetPointSize (Points);
    SetFont (Font); 
  
    PathDelimiter = wxT ("");
    PathDelimiter += PATH_DELIMITER;

    // Find the directory that the executable is in.  Then go up one
    // level and then down into Resources sub-directory.  I envision
    // the installation directory structure to be something like
    //	 .../VirtualAGC/bin
    // 	 .../VirtualAGC/Resources
    // in Win32 and Linux, and to be
    //   .../VirtualAGC.app/Contents/MacOS
    //   .../VirtualAGC.app/Contents/Resources
    // in Mac OS X.  The commonality here is the relative relationship
    // of the executables to the data files such as png images.
    ExecutableDirectory = StandardPaths.GetExecutablePath().BeforeLast (PATH_DELIMITER);
#ifdef __FreeBSD__    
    // In FreeBSD, for some reason, the operation above sometimes or always
    // returns a relative path rather than an absolute one.  So we need to convert
    // it to an absolute path.
    if (ExecutableDirectory.GetChar (0) != '/')
      {
        wxString WorkingDir = wxGetCwd ();
	ExecutableDirectory = WorkingDir + PATH_DELIMITER + ExecutableDirectory;
      }
#endif
    wxString TopDirectory = ExecutableDirectory.BeforeLast (PATH_DELIMITER);
    TopDirectory += PathDelimiter;
    RunDirectory = TopDirectory + wxT ("Simulation");
    ResourceDirectory = TopDirectory + wxT ("Resources");
    //wxMessageBox (ResourceDirectory, wxT ("Resource path"));
    wxSetWorkingDirectory (ResourceDirectory);
    //wxMessageBox (wxGetCwd (), wxT ("Working directory"));
    
    // begin wxGlade: VirtualAGC::VirtualAGC
    sizer_1_copy_staticbox = new wxStaticBox(this, -1, wxT("Browse Source Code"));
    sizer_20_staticbox = new wxStaticBox(this, -1, wxT("LM Abort Computer (AEA)"));
    sizer_18_staticbox = new wxStaticBox(this, -1, wxT("AGC Startup"));
    sizer_21_staticbox = new wxStaticBox(this, -1, wxT("DSKY Type"));
    sizer_28_staticbox = new wxStaticBox(this, -1, wxT("Telemetry Style"));
    sizer_22_staticbox = new wxStaticBox(this, -1, wxT("AGC Debug"));
    sizer_24_staticbox = new wxStaticBox(this, -1, wxT("DEDA type"));
    sizer_23_staticbox = new wxStaticBox(this, -1, wxT("AEA Debug"));
    sizer_19_staticbox = new wxStaticBox(this, -1, wxT("Guidance Computer (AGC)"));
    Patch1Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo1.png"), wxBITMAP_TYPE_ANY));
    Patch7Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo7.png"), wxBITMAP_TYPE_ANY));
    Patch8Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo8.png"), wxBITMAP_TYPE_ANY));
    Patch9Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo9.png"), wxBITMAP_TYPE_ANY));
    Patch10Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo10.png"), wxBITMAP_TYPE_ANY));
    Patch11Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo11.png"), wxBITMAP_TYPE_ANY));
    PatchBitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("ApolloPatch2.png"), wxBITMAP_TYPE_ANY));
    Patch12Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo12.png"), wxBITMAP_TYPE_ANY));
    Patch13Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo13.png"), wxBITMAP_TYPE_ANY));
    Patch14Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo14.png"), wxBITMAP_TYPE_ANY));
    Patch15Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo15.png"), wxBITMAP_TYPE_ANY));
    Patch16Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo16.png"), wxBITMAP_TYPE_ANY));
    Patch17Bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("apo17.png"), wxBITMAP_TYPE_ANY));
    TopLine = new wxStaticLine(this, wxID_ANY);
    SimTypeLabel = new wxStaticText(this, wxID_ANY, wxT("Simulation Type"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
    Apollo7CmButton = new wxRadioButton(this, ID_APOLLO7CMBUTTON, wxT("Apollo 7 Command Module"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    Colossus249Button = new wxRadioButton(this, ID_COLOSSUS249BUTTON, wxT("Apollo 8 Command Module"));
    Apollo9CmButton = new wxRadioButton(this, ID_APOLLO9CMBUTTON, wxT("Apollo 9 Command Module"));
    Apollo9LmButton = new wxRadioButton(this, ID_APOLLO9LMBUTTON, wxT("Apollo 9 Lunar Module"));
    Apollo10CmButton = new wxRadioButton(this, ID_APOLLO10CMBUTTON, wxT("Apollo 10 Command Module"));
    Apollo10LmButton = new wxRadioButton(this, ID_APOLLO10LMBUTTON, wxT("Apollo 10 Lunar Module"));
    Comanche55Button = new wxRadioButton(this, ID_COMANCHE55BUTTON, wxT("Apollo 11 Command Module"));
    Luminary99Button = new wxRadioButton(this, ID_LUMINARY99BUTTON, wxT("Apollo 11 Lunar Module"));
    Apollo12CmButton = new wxRadioButton(this, ID_APOLLO12CMBUTTON, wxT("Apollo 12 Command Module"));
    Apollo12LmButton = new wxRadioButton(this, ID_APOLLO12LMBUTTON, wxT("Apollo 12 Lunar Module"));
    Apollo13CmButton = new wxRadioButton(this, ID_APOLLO13CMBUTTON, wxT("Apollo 13 Command Module"));
    Luminary131Button = new wxRadioButton(this, ID_LUMINARY131BUTTON, wxT("Apollo 13 Lunar Module"));
    Apollo14CmButton = new wxRadioButton(this, ID_APOLLO14CMBUTTON, wxT("Apollo 14 Command Module"));
    Apollo14LmButton = new wxRadioButton(this, ID_APOLLO14LMBUTTON, wxT("Apollo 14 Lunar Module"));
    Artemis72Button = new wxRadioButton(this, ID_ARTEMIS72BUTTON, wxT("Apollo 15-17 Command Module"));
    Apollo15LmButton = new wxRadioButton(this, ID_APOLLO15LMBUTTON, wxT("Apollo 15-17 Lunar Module"));
    ValidationButton = new wxRadioButton(this, ID_VALIDATIONBUTTON, wxT("Validation Suite"));
    AgcCustomButton = new wxRadioButton(this, ID_AGCCUSTOMBUTTON, wxT("Custom:"));
    AgcCustomFilename = new wxTextCtrl(this, ID_AGCCUSTOMFILENAME, wxEmptyString);
    AgcFilenameBrowse = new wxButton(this, ID_AGCFILENAMEBROWSE, wxT("..."));
    AgcSourceButton = new wxButton(this, ID_AGCSOURCEBUTTON, wxT("AGC"));
    AeaSourceButton = new wxButton(this, ID_AEASOURCEBUTTON, wxT("AEA"));
    static_line_2 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
    DeviceListLabel = new wxStaticText(this, wxID_ANY, wxT("Interfaces"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
    DeviceAgcCheckbox = new wxCheckBox(this, ID_DEVICEAGCCHECKBOX, wxT("Guidance Computer"));
    DeviceDskyCheckbox = new wxCheckBox(this, ID_DEVICEDSKYCHECKBOX, wxT("DSKY (AGC display and keypad)"));
    DeviceAcaCheckbox = new wxCheckBox(this, ID_DEVICEACACHECKBOX, wxT("Attitude Controller Assembly (control-stick)"));
    DeviceTelemetryCheckbox = new wxCheckBox(this, ID_DEVICETELEMETRYCHECKBOX, wxT("Telemetry Downlink Monitor"));
    DeviceAeaCheckbox = new wxCheckBox(this, ID_DEVICEAEACHECKBOX, wxT("LM Abort Computer (AEA)"));
    DeviceDedaCheckbox = new wxCheckBox(this, ID_DEVICEDEDACHECKBOX, wxT("DEDA (AEA display and keypad)"));
    DeviceCpumonCheckbox = new wxCheckBox(this, ID_DEVICECPUMONCHECKBOX, wxT("AGC CPU Bus/Input/Output Monitor"));
    static_line_4 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
    DeviceImuCheckbox = new wxCheckBox(this, ID_DEVICEIMUCHECKBOX, wxT("Inertial Monitor Unit / FDAI (8-ball)"));
    DeviceDiscoutCheckbox = new wxCheckBox(this, ID_DEVICEDISCOUTCHECKBOX, wxT("Discrete Outputs"));
    DeviceCrewinCheckbox = new wxCheckBox(this, ID_DEVICECREWINCHECKBOX, wxT("Discrete Inputs (crew)"));
    DeviceSysinCheckbox = new wxCheckBox(this, ID_DEVICESYSINCHECKBOX, wxT("Discrete Inputs (LM system)"));
    DevicePropulsionCheckbox = new wxCheckBox(this, ID_DEVICEPROPULSIONCHECKBOX, wxT("Propulsion/Thrust/Fuel Monitor"));
    NoviceButton = new wxButton(this, ID_NOVICEBUTTON, wxT("Novice"));
    ExpertButton = new wxButton(this, ID_EXPERTBUTTON, wxT("Expert"));
    FlightProgram4Button = new wxRadioButton(this, ID_FLIGHTPROGRAM4BUTTON, wxT("Apollo 9 (Flight Programs 3, 4)"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    FlightProgram5Button = new wxRadioButton(this, ID_FLIGHTPROGRAM5BUTTON, wxT("Apollo 10 (Flight Program 5)"));
    FlightProgram6Button = new wxRadioButton(this, ID_FLIGHTPROGRAM6BUTTON, wxT("Apollo 11 (Flight Program 6)"));
    FlightProgram7Button = new wxRadioButton(this, ID_FLIGHTPROGRAM7BUTTON, wxT("Apollo 12-14? (Flight Program 7)"));
    FlightProgram8Button = new wxRadioButton(this, ID_FLIGHTPROGRAM8BUTTON, wxT("Apollo 15-17 (Flight Program 8)"));
    AeaCustomButton = new wxRadioButton(this, ID_AEACUSTOMBUTTON, wxT("Custom:"));
    AeaCustomFilename = new wxTextCtrl(this, ID_AEACUSTOMFILENAME, wxEmptyString);
    AeaFilenameBrowse = new wxButton(this, ID_AEAFILENAMEBROWSE, wxT("..."));
    static_line_3 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
    OptionList = new wxStaticText(this, wxID_ANY, wxT("Options"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
    StartupWipeButton = new wxRadioButton(this, ID_STARTUPWIPEBUTTON, wxT("Restart program, wiping memory"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    StartupPreserveButton = new wxRadioButton(this, ID_STARTUPPRESERVEBUTTON, wxT("Restart program, preserving memory"));
    StartupResumeButton = new wxRadioButton(this, ID_STARTUPRESUMEBUTTON, wxT("Resume from ending point of prior run"));
    CustomResumeButton = new wxRadioButton(this, ID_CUSTOMRESUMEBUTTON, wxT("Custom:"));
    CoreFilename = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
    CoreBrowse = new wxButton(this, ID_COREBROWSE, wxT("..."));
    CoreSaveButton = new wxButton(this, ID_CORESAVEBUTTON, wxT("Save"));
    DskyFullButton = new wxRadioButton(this, ID_DSKYFULLBUTTON, wxT("Normal (Virtual AGC)"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    DskyHalfButton = new wxRadioButton(this, ID_DSKYHALFBUTTON, wxT("Half-size (Virtual AGC)"));
    DskyLiteButton = new wxRadioButton(this, ID_DSKYLITEBUTTON, wxT("Lite (LM-Simulator)"));
    TelemetryResizable = new wxRadioButton(this, wxID_ANY, wxT("Resizable"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    TelemetryRetro = new wxRadioButton(this, wxID_ANY, wxT("Retro"));
    AgcDebugNormalButton = new wxRadioButton(this, ID_AGCDEBUGNORMALBUTTON, wxT("Normal execution (no debugging)"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    AgcDebugMonitorButton = new wxRadioButton(this, ID_AGCDEBUGMONITORBUTTON, wxT("Run with debug monitor"));
    DedaFullButton = new wxRadioButton(this, ID_DEDAFULLBUTTON, wxT("Normal size"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    DedaHalfButton = new wxRadioButton(this, ID_DEDAHALFBUTTON, wxT("Half-size"));
    AeaDebugNormalButton = new wxRadioButton(this, ID_AEADEBUGNORMALBUTTON, wxT("Normal execution (no debugging)"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    AeaDebugMonitorButton = new wxRadioButton(this, ID_AEADEBUGMONITORBUTTON, wxT("Run with debug monitor"));
    static_line_1 = new wxStaticLine(this, wxID_ANY);
    RunButton = new wxButton(this, ID_RUNBUTTON, wxT("Run!"));
    DefaultsButton = new wxButton(this, ID_DEFAULTSBUTTON, wxT("Defaults"));
    ExitButton = new wxButton(this, ID_EXITBUTTON, wxT("Exit"));

    set_properties();
    do_layout();
    // end wxGlade
    
    SetDefaultConfiguration ();
    ReadConfigurationFile ();
    Comanche55Button->Enable (false);
    Luminary99Button->Enable (false);
    EnforceConsistency ();
    
    SetSize ();
    Layout ();
    Fit ();
}


BEGIN_EVENT_TABLE(VirtualAGC, wxFrame)
    // begin wxGlade: VirtualAGC::event_table
    EVT_RADIOBUTTON(ID_APOLLO7CMBUTTON, VirtualAGC::Apollo7CmEvent)
    EVT_RADIOBUTTON(ID_COLOSSUS249BUTTON, VirtualAGC::Colossus249Event)
    EVT_RADIOBUTTON(ID_APOLLO9CMBUTTON, VirtualAGC::Apollo9CmEvent)
    EVT_RADIOBUTTON(ID_APOLLO9LMBUTTON, VirtualAGC::Apollo9LmEvent)
    EVT_RADIOBUTTON(ID_APOLLO10CMBUTTON, VirtualAGC::Apollo10CmEvent)
    EVT_RADIOBUTTON(ID_APOLLO10LMBUTTON, VirtualAGC::Apollo10LmEvent)
    EVT_RADIOBUTTON(ID_COMANCHE55BUTTON, VirtualAGC::Comanche55Event)
    EVT_RADIOBUTTON(ID_LUMINARY99BUTTON, VirtualAGC::Luminary99Event)
    EVT_RADIOBUTTON(ID_APOLLO12CMBUTTON, VirtualAGC::Apollo12CmEvent)
    EVT_RADIOBUTTON(ID_APOLLO12LMBUTTON, VirtualAGC::Apollo12LmEvent)
    EVT_RADIOBUTTON(ID_APOLLO13CMBUTTON, VirtualAGC::Apollo13CmEvent)
    EVT_RADIOBUTTON(ID_LUMINARY131BUTTON, VirtualAGC::Luminary131Event)
    EVT_RADIOBUTTON(ID_APOLLO14CMBUTTON, VirtualAGC::Apollo14CmEvent)
    EVT_RADIOBUTTON(ID_APOLLO14LMBUTTON, VirtualAGC::Apollo14LmEvent)
    EVT_RADIOBUTTON(ID_ARTEMIS72BUTTON, VirtualAGC::Artemis72Event)
    EVT_RADIOBUTTON(ID_APOLLO15LMBUTTON, VirtualAGC::Apollo15LmEvent)
    EVT_RADIOBUTTON(ID_VALIDATIONBUTTON, VirtualAGC::ValidationEvent)
    EVT_RADIOBUTTON(ID_AGCCUSTOMBUTTON, VirtualAGC::AgcCustomEvent)
    EVT_BUTTON(ID_AGCFILENAMEBROWSE, VirtualAGC::AgcFilenameBrowseEvent)
    EVT_BUTTON(ID_AGCSOURCEBUTTON, VirtualAGC::AgcSourceEvent)
    EVT_BUTTON(ID_AEASOURCEBUTTON, VirtualAGC::AeaSourceEvent)
    EVT_CHECKBOX(ID_DEVICEAGCCHECKBOX, VirtualAGC::DeviceAgcEvent)
    EVT_CHECKBOX(ID_DEVICEDSKYCHECKBOX, VirtualAGC::DeviceDskyEvent)
    EVT_CHECKBOX(ID_DEVICEACACHECKBOX, VirtualAGC::DeviceAcaEvent)
    EVT_CHECKBOX(ID_DEVICETELEMETRYCHECKBOX, VirtualAGC::DeviceTelemetryEvent)
    EVT_CHECKBOX(ID_DEVICEAEACHECKBOX, VirtualAGC::DeviceAeaEvent)
    EVT_CHECKBOX(ID_DEVICEDEDACHECKBOX, VirtualAGC::DeviceDedaEvent)
    EVT_CHECKBOX(ID_DEVICECPUMONCHECKBOX, VirtualAGC::DeviceCpumonEvent)
    EVT_CHECKBOX(ID_DEVICEIMUCHECKBOX, VirtualAGC::DeviceImuEvent)
    EVT_CHECKBOX(ID_DEVICEDISCOUTCHECKBOX, VirtualAGC::DeviceDiscoutEvent)
    EVT_CHECKBOX(ID_DEVICECREWINCHECKBOX, VirtualAGC::DeviceCrewinEvent)
    EVT_CHECKBOX(ID_DEVICESYSINCHECKBOX, VirtualAGC::DeviceSysinEvent)
    EVT_CHECKBOX(ID_DEVICEPROPULSIONCHECKBOX, VirtualAGC::DevicePropulsionEvent)
    EVT_BUTTON(ID_NOVICEBUTTON, VirtualAGC::NoviceButtonEvent)
    EVT_BUTTON(ID_EXPERTBUTTON, VirtualAGC::ExpertButtonEvent)
    EVT_RADIOBUTTON(ID_FLIGHTPROGRAM4BUTTON, VirtualAGC::FlightProgram4Event)
    EVT_RADIOBUTTON(ID_FLIGHTPROGRAM5BUTTON, VirtualAGC::FlightProgram5Event)
    EVT_RADIOBUTTON(ID_FLIGHTPROGRAM6BUTTON, VirtualAGC::FlightProgram6Event)
    EVT_RADIOBUTTON(ID_FLIGHTPROGRAM7BUTTON, VirtualAGC::FlightProgram7Event)
    EVT_RADIOBUTTON(ID_FLIGHTPROGRAM8BUTTON, VirtualAGC::FlightProgram8Event)
    EVT_RADIOBUTTON(ID_AEACUSTOMBUTTON, VirtualAGC::AeaCustomEvent)
    EVT_BUTTON(ID_AEAFILENAMEBROWSE, VirtualAGC::AeaFilenameBrowseEvent)
    EVT_RADIOBUTTON(ID_STARTUPWIPEBUTTON, VirtualAGC::StartupWipeEvent)
    EVT_RADIOBUTTON(ID_STARTUPPRESERVEBUTTON, VirtualAGC::StartupPreserveEvent)
    EVT_RADIOBUTTON(ID_STARTUPRESUMEBUTTON, VirtualAGC::StartupResumeEvent)
    EVT_RADIOBUTTON(ID_CUSTOMRESUMEBUTTON, VirtualAGC::CustomCoreClick)
    EVT_BUTTON(ID_COREBROWSE, VirtualAGC::CoreBrowseEvent)
    EVT_BUTTON(ID_CORESAVEBUTTON, VirtualAGC::CoreSaveEvent)
    EVT_RADIOBUTTON(ID_DSKYFULLBUTTON, VirtualAGC::DskyFullEvent)
    EVT_RADIOBUTTON(ID_DSKYHALFBUTTON, VirtualAGC::DskyHalfEvent)
    EVT_RADIOBUTTON(ID_DSKYLITEBUTTON, VirtualAGC::DskyLiteEvent)
    EVT_RADIOBUTTON(ID_AGCDEBUGNORMALBUTTON, VirtualAGC::AgcDebugNormalEvent)
    EVT_RADIOBUTTON(ID_AGCDEBUGMONITORBUTTON, VirtualAGC::AgcDebugMonitorEvent)
    EVT_RADIOBUTTON(ID_DEDAFULLBUTTON, VirtualAGC::DedaFullEvent)
    EVT_RADIOBUTTON(ID_DEDAHALFBUTTON, VirtualAGC::DedaHalfEvent)
    EVT_RADIOBUTTON(ID_AEADEBUGNORMALBUTTON, VirtualAGC::AeaDebugNormalEvent)
    EVT_RADIOBUTTON(ID_AEADEBUGMONITORBUTTON, VirtualAGC::AeaDebugMonitorEvent)
    EVT_BUTTON(ID_RUNBUTTON, VirtualAGC::RunButtonEvent)
    EVT_BUTTON(ID_DEFAULTSBUTTON, VirtualAGC::DefaultsButtonEvent)
    EVT_BUTTON(ID_EXITBUTTON, VirtualAGC::ExitButtonEvent)
    // end wxGlade
END_EVENT_TABLE();


#define TEMPTRACE(x) //wxMessageBox (wxT ("Trace"), wxT (x))

void VirtualAGC::AgcFilenameBrowseEvent(wxCommandEvent &event)
{
    TEMPTRACE ("2");
    wxFileDialog *Dialog = new wxFileDialog (this, wxT ("Choose AGC executable-binary file"),
    					     AgcDirectory, wxT (""), 
					     wxT ("Source files (*.s)|*.s|Binary files (*.bin)|*.bin"),
					     wxFD_DEFAULT_STYLE | 
					     wxFD_FILE_MUST_EXIST | 
					     wxFD_CHANGE_DIR);  
    Dialog->SetPath (AgcCustomFilename->GetValue ());
    if (wxID_OK == Dialog->ShowModal ())
      {
	wxString Pathname = Dialog->GetPath ();  
	wxString Basename = Pathname.BeforeLast ('.');
	wxString Extension = Pathname.AfterLast ('.');
	wxString Filename = Dialog->GetFilename ();
	wxString Filebase = Filename.BeforeLast ('.');
	wxString Directory = Dialog->GetDirectory ();
	if (Extension.IsSameAs (wxT ("s")))  // Source code!
	  {
	    if (Pathname.StartsWith (ResourceDirectory))
	      {
	        if (wxYES != wxMessageBox (wxT ("This source file is in the installation directory.\n"
		                   		"Assembling it may overwrite some of Virtual AGC\'s\n"
				   		"distribution files.  Are you sure?"), 
					   wxT ("Warning"),
				           wxYES_NO | wxICON_QUESTION))
		  goto Done;
	      }
	    // Check whether final output files or intermediate files that might
	    // have been created from a command-line assembly already exist.
	    wxString Dummy, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5;
	    Dummy1 = Basename + wxT (".lst");
	    Dummy2 = Pathname + wxT (".bin");
	    Dummy3 = Basename + wxT (".bin");
	    Dummy4 = Pathname + wxT (".symtab");
	    Dummy5 = Basename + wxT (".bin.symtab");
	    if (wxFileExists (Dummy1))
	      Dummy += wxT ("\n   ") + Dummy1;
	    if (wxFileExists (Dummy2))
	      Dummy += wxT ("\n   ") + Dummy2;
	    if (wxFileExists (Dummy3))
	      Dummy += wxT ("\n   ") + Dummy3;
	    if (wxFileExists (Dummy4))
	      Dummy += wxT ("\n   ") + Dummy4;
	    if (wxFileExists (Dummy5))
	      Dummy += wxT ("\n   ") + Dummy5;
	    if (!Dummy.IsSameAs (wxT ("")))
	      {
	        Dummy = wxT ("The following output/intermediate files exist.") + Dummy;
		Dummy += wxT ("\nOverwrite them?");
	        if (wxYES != wxMessageBox (Dummy, wxT ("Warning"), wxYES_NO | wxICON_QUESTION))
		  goto Done;
	      }
	    // Okay, the user has agreed to everything.  Let's create a batch file or
	    // shell script to do the assembly, and then run it.
	    wxFile BuildScript;
	    wxString MvCommand, RmCommand, BuildFilename;
#ifdef WIN32
	    MvCommand = wxT ("move");
	    RmCommand = wxT ("del");
	    BuildFilename = wxT ("build.bat");
#else
	    MvCommand = wxT ("mv");
	    RmCommand = wxT ("rm");
	    BuildFilename = wxT ("build.sh");
#endif	    
	    if (!BuildScript.Open (BuildFilename, wxFile::write))
	      {
	        wxMessageBox (wxT ("Could not create the build script."), wxT ("Error"), wxOK | wxICON_ERROR);
	        goto Done;
	      }
	    Dummy = wxT ("cd \"") + Directory + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Dummy1 + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Dummy2 + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Dummy3 + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Dummy4 + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Dummy5 + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = wxT ("\"");
	    Dummy += ExecutableDirectory;
	    Dummy += PATH_DELIMITER;
	    Dummy += wxT ("yaYUL\" \"");
	    Dummy += Filename;
	    Dummy += wxT ("\" >\"") + Filebase + wxT (".lst\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = MvCommand + wxT (" \"") + Filename + wxT (".bin\" \"") + Filebase + wxT (".bin\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = MvCommand + wxT (" \"") + Filename + wxT (".symtab\" \"") + Filebase + wxT (".bin.symtab\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    BuildScript.Close ();
	    // Do it!
#ifndef WIN32
	    BuildFilename = wxT ("sh ") + BuildFilename;
#endif	    
	    wxExecute (BuildFilename, wxEXEC_SYNC);
	    Dummy = Basename + wxT (".bin");
	    if (!wxFileExists (Dummy))
	      {
	        Dummy = wxT ("There was an assembly error. Examine the report\n");
		Dummy += Basename + wxT (".lst");
	        wxMessageBox (Dummy, wxT ("Error"), wxOK | wxICON_ERROR);
		  goto Done;
	      }
	    wxFile BinaryFile;
	    BinaryFile.Open (Dummy);
	    int Length = BinaryFile.Length ();
	    BinaryFile.Close ();
	    if (Length == 0)
	      {
	        Dummy = wxT ("There was an assembly error. Examine the report\n");
		Dummy += Basename + wxT (".lst");
	        wxMessageBox (Dummy, wxT ("Error"), wxOK | wxICON_ERROR);
		  goto Done;
	      }
	    Dummy = wxT ("Created in ") + Directory + wxT (":");
	    Dummy += wxT ("\n   Binary: ") + Filebase + wxT (".bin");
	    Dummy += wxT ("\n   Symbol table: ") + Filebase + wxT (".bin.symtab");
	    Dummy += wxT ("\n   Listing: ") + Filebase + wxT (".lst");
	    wxMessageBox (Dummy, wxT ("Info"), wxICON_INFORMATION);
	  }
	Pathname = Basename + wxT (".bin");
	AgcCustomFilename->SetValue (Pathname);  
	AgcDirectory = Directory;
      }
Done:      
    delete Dialog;
    wxSetWorkingDirectory (ResourceDirectory);
}


void VirtualAGC::AeaFilenameBrowseEvent(wxCommandEvent &event)
{
    TEMPTRACE ("4");
    wxFileDialog *Dialog = new wxFileDialog (this, wxT ("Choose AEA/AGS executable-binary file"),
    					     AeaDirectory, wxT (""), 
					     wxT ("Source files (*.s)|*.s|Binary files (*.bin)|*.bin"),
					     wxFD_DEFAULT_STYLE | 
					     wxFD_FILE_MUST_EXIST | 
					     wxFD_CHANGE_DIR);  
    Dialog->SetPath (AeaCustomFilename->GetValue ());
    if (wxID_OK == Dialog->ShowModal ())
      {
	wxString Pathname = Dialog->GetPath ();  
	wxString Basename = Pathname.BeforeLast ('.');
	wxString Extension = Pathname.AfterLast ('.');
	wxString Filename = Dialog->GetFilename ();
	wxString Filebase = Filename.BeforeLast ('.');
	wxString Directory = Dialog->GetDirectory ();
	if (Extension.IsSameAs (wxT ("s")))  // Source code!
	  {
	    if (Pathname.StartsWith (ResourceDirectory))
	      {
	        if (wxYES != wxMessageBox (wxT ("This source file is in the installation directory.\n"
		                   		"Assembling it may overwrite some of Virtual AGC\'s\n"
				   		"distribution files.  Are you sure?"), 
					   wxT ("Warning"),
				           wxYES_NO | wxICON_QUESTION))
		  goto Done;
	      }
	    // Check whether final output files or intermediate files that might
	    // have been created from a command-line assembly already exist.
	    wxString Dummy, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5, Dummy6;
	    Dummy1 = Basename + wxT (".lst");
	    Dummy2 = wxT ("yaLEMAP.lst");
	    Dummy3 = Basename + wxT (".bin");
	    Dummy4 = wxT ("yaLEMAP.bin");
	    Dummy5 = Basename + wxT (".bin.symtab");
	    Dummy4 = wxT ("yaLEMAP.symtab");
	    if (wxFileExists (Dummy2))
	      Dummy += wxT ("\n   ") + Dummy2;
	    if (wxFileExists (Dummy4))
	      Dummy += wxT ("\n   ") + Dummy4;
	    if (wxFileExists (Dummy6))
	      Dummy += wxT ("\n   ") + Dummy6;
	    if (wxFileExists (Dummy1))
	      Dummy += wxT ("\n   ") + Dummy1;
	    if (wxFileExists (Dummy3))
	      Dummy += wxT ("\n   ") + Dummy3;
	    if (wxFileExists (Dummy5))
	      Dummy += wxT ("\n   ") + Dummy5;
	    if (!Dummy.IsSameAs (wxT ("")))
	      {
	        Dummy = wxT ("The following intermediate/output files exist.") + Dummy;
		Dummy += wxT ("\nOverwrite them?");
	        if (wxYES != wxMessageBox (Dummy, wxT ("Warning"), wxYES_NO | wxICON_QUESTION))
		  goto Done;
	      }
	    // Okay, the user has agreed to everything.  Let's create a batch file or
	    // shell script to do the assembly, and then run it.
	    wxFile BuildScript;
	    wxString MvCommand, RmCommand, BuildFilename;
#ifdef WIN32
	    MvCommand = wxT ("move");
	    RmCommand = wxT ("del");
	    BuildFilename = wxT ("build.bat");
#else
	    MvCommand = wxT ("mv");
	    RmCommand = wxT ("rm");
	    BuildFilename = wxT ("build.sh");
#endif	    
	    if (!BuildScript.Open (BuildFilename, wxFile::write))
	      {
	        wxMessageBox (wxT ("Could not create the build script."), wxT ("Error"), wxOK | wxICON_ERROR);
	        goto Done;
	      }
	    Dummy = wxT ("cd \"") + Directory + wxT ("\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Filebase + wxT (".bin\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Filebase + wxT (".bin.symtab\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT (" \"") + Filebase + wxT (".lst\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT ("yaLEMAP.bin");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT ("yaLEMAP.symtab");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = RmCommand + wxT ("yaLEMAP.lst");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = wxT ("\"");
	    Dummy += ExecutableDirectory;
	    Dummy += PATH_DELIMITER;
	    Dummy += wxT ("yaLEMAP\" ");
	    Dummy += Filename;
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = MvCommand + wxT (" yaLEMAP.bin \"") + Filebase + wxT (".bin\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = MvCommand + wxT (" yaLEMAP.symtab \"") + Filebase + wxT (".bin.symtab\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    Dummy = MvCommand + wxT (" yaLEMAP.lst \"") + Filebase + wxT (".lst\"");
	    Dummy += wxT (EOL);
	    BuildScript.Write (Dummy);
	    BuildScript.Close ();
	    // Do it!
#ifndef WIN32
	    BuildFilename = wxT ("sh ") + BuildFilename;
#endif	    
	    wxExecute (BuildFilename, wxEXEC_SYNC);
	    Dummy = Basename + wxT (".bin");
	    if (!wxFileExists (Dummy))
	      {
	        Dummy = wxT ("There was an assembly error. Examine the report\n");
		Dummy += Basename + wxT (".lst");
	        wxMessageBox (Dummy, wxT ("Error"), wxOK | wxICON_ERROR);
		  goto Done;
	      }
	    wxFile BinaryFile;
	    BinaryFile.Open (Dummy);
	    int Length = BinaryFile.Length ();
	    BinaryFile.Close ();
	    if (Length == 0)
	      {
	        Dummy = wxT ("There was an assembly error. Examine the report\n");
		Dummy += Basename + wxT (".lst");
	        wxMessageBox (Dummy, wxT ("Error"), wxOK | wxICON_ERROR);
		  goto Done;
	      }
	    Dummy = wxT ("Created in ") + Directory + wxT (":");
	    Dummy += wxT ("\n   Binary: ") + Filebase + wxT (".bin");
	    Dummy += wxT ("\n   Symbol table: ") + Filebase + wxT (".bin.symtab");
	    Dummy += wxT ("\n   Listing: ") + Filebase + wxT (".lst");
	    wxMessageBox (Dummy, wxT ("Info"), wxICON_INFORMATION);
	  }
	Pathname = Basename + wxT (".bin");
	AeaCustomFilename->SetValue (Pathname);  
	AeaDirectory = Directory;
      }
Done:      
    delete Dialog;
    wxSetWorkingDirectory (ResourceDirectory);
}


void VirtualAGC::CoreBrowseEvent(wxCommandEvent &event)
{
    wxString ScenarioDirectory;
    ScenarioDirectory = ResourceDirectory;
    ScenarioDirectory += PATH_DELIMITER;
    ScenarioDirectory += wxT ("scenarios");
    wxFileDialog *Dialog = new wxFileDialog (this, wxT ("Choose core-dump file for resumption"),
    					     ScenarioDirectory , wxT (""), 
					     wxT ("Core-dump files (*.core)|*.core|All files (*)|*"),
					     wxFD_DEFAULT_STYLE | 
					     wxFD_FILE_MUST_EXIST | 
					     wxFD_CHANGE_DIR);  
    if (wxID_OK == Dialog->ShowModal ())
      {
	wxString Pathname = Dialog->GetPath ();  
	CoreFilename->SetValue (Pathname);  
      }
    delete Dialog;
    wxSetWorkingDirectory (ResourceDirectory);
}


void VirtualAGC::CoreSaveEvent(wxCommandEvent &event)
{
    wxString ScenarioDirectory;
    ScenarioDirectory = ResourceDirectory;
    ScenarioDirectory += PATH_DELIMITER;
    ScenarioDirectory += wxT ("scenarios");
    wxString CoreFile;
    int Response;
    if (IsLM)
      CoreFile = wxT ("LM.core");
    else
      CoreFile = wxT ("CM.core");
    Response = wxMessageBox (wxT ("Do you wish to save ") + CoreFile, 
    			     wxT ("Core-dump file to save"), 
			     wxYES_NO | wxICON_QUESTION);
    if (Response == wxYES && !wxFileExists (CoreFile))
      {
        wxMessageBox (wxT ("File does not exist"), wxT ("Error"), wxICON_ERROR);
	goto Done;
      }
    if (Response == wxNO)
      {
	wxFileDialog *DialogR = new wxFileDialog (this, wxT ("Choose core-dump file to save"),
						 wxT ("") , wxT (""), 
						 wxT ("Core-dump files (*.core)|*.core|All files (*)|*"),
						 wxFD_DEFAULT_STYLE | 
						 wxFD_FILE_MUST_EXIST | 
						 wxFD_CHANGE_DIR);  
	if (wxID_OK == DialogR->ShowModal ())
	  {
	    wxString CoreFile = DialogR->GetPath ();  
	    delete DialogR;
	  }
	else
	  {
	    delete DialogR;
	    goto Done;
	  }
      }
    {
      wxFileDialog *DialogS = new wxFileDialog (this, wxT ("Save core-dump file as"),
					       ScenarioDirectory , wxT (""), 
					       wxT ("Core-dump files (*.core)|*.core|All files (*)|*"),
					       wxFD_DEFAULT_STYLE | 
					       wxFD_CHANGE_DIR | wxFD_SAVE |
					       wxFD_OVERWRITE_PROMPT);  
      if (wxID_OK == DialogS->ShowModal ())
	{
	  wxString Pathname = DialogS->GetPath ();
	  if (!Pathname.AfterLast('.').IsSameAs(wxT ("core")))
	    wxMessageBox (wxT ("Note that you did not add the .core extension.\n"
	    		       "If you browse for core files later, you will\n"
			       "not see this file as a Core File and will have\n"
			       "to select All Files for it to show up."), 
			  wxT ("Warning"), wxICON_WARNING); 
	  CoreFilename->SetValue (Pathname);  
          wxSetWorkingDirectory (ResourceDirectory);
	  wxCopyFile (CoreFile, Pathname, true);
	  CustomResumeButton->SetValue (true);
	  EnforceConsistency ();
	}
      delete DialogS;
    }
Done:      
    wxSetWorkingDirectory (ResourceDirectory);
}


void VirtualAGC::DeviceAgcEvent(wxCommandEvent &event)
{
    TEMPTRACE ("5");
    EnforceConsistency ();
}


void VirtualAGC::DeviceDskyEvent(wxCommandEvent &event)
{
    TEMPTRACE ("6");
    EnforceConsistency ();
}


void VirtualAGC::DeviceAcaEvent(wxCommandEvent &event)
{
    TEMPTRACE ("7");
    EnforceConsistency ();
}


void VirtualAGC::DeviceTelemetryEvent(wxCommandEvent &event)
{
    TEMPTRACE ("8");
    EnforceConsistency ();
}


void VirtualAGC::DeviceAeaEvent(wxCommandEvent &event)
{
    TEMPTRACE ("9");
    EnforceConsistency ();
}


void VirtualAGC::DeviceDedaEvent(wxCommandEvent &event)
{
    TEMPTRACE ("10");
    EnforceConsistency ();
}


void VirtualAGC::DeviceCpumonEvent(wxCommandEvent &event)
{
    TEMPTRACE ("11");
    EnforceConsistency ();
}


void VirtualAGC::DeviceImuEvent(wxCommandEvent &event)
{
    TEMPTRACE ("12");
    EnforceConsistency ();
}


void VirtualAGC::DeviceDiscoutEvent(wxCommandEvent &event)
{
    TEMPTRACE ("13");
    EnforceConsistency ();
}


void VirtualAGC::DeviceCrewinEvent(wxCommandEvent &event)
{
    TEMPTRACE ("14");
    EnforceConsistency ();
}


void VirtualAGC::DeviceSysinEvent(wxCommandEvent &event)
{
    TEMPTRACE ("15");
    EnforceConsistency ();
}


void VirtualAGC::DevicePropulsionEvent(wxCommandEvent &event)
{
    TEMPTRACE ("16");
    EnforceConsistency ();
}


void VirtualAGC::NoviceButtonEvent(wxCommandEvent &event)
{
    TEMPTRACE ("17");
    DeviceAcaCheckbox->SetValue (false);
    DeviceTelemetryCheckbox->SetValue (false);
    DeviceAeaCheckbox->SetValue (false);
    DeviceCpumonCheckbox->SetValue (false);
    StartupWipeButton->SetValue (true);
    AgcDebugNormalButton->SetValue (true);
    EnforceConsistency ();
}


void VirtualAGC::ExpertButtonEvent(wxCommandEvent &event)
{
    TEMPTRACE ("18");
    DeviceAcaCheckbox->SetValue (true);
    DeviceTelemetryCheckbox->SetValue (true);
    DeviceAeaCheckbox->SetValue (true);
    DeviceCpumonCheckbox->SetValue (true);
    DeviceImuCheckbox->SetValue (true);
    DeviceDiscoutCheckbox->SetValue (true);
    DeviceCrewinCheckbox->SetValue (true);
    DeviceSysinCheckbox->SetValue (true);
    DevicePropulsionCheckbox->SetValue (true);
    EnforceConsistency ();
}


void VirtualAGC::RunButtonEvent(wxCommandEvent &event)
{
    TEMPTRACE ("24");
    wxSetWorkingDirectory (ResourceDirectory);
    if (DeviceCpumonCheckbox->GetValue ())
      {
	if (!FormLmsIni ())
	  return;
      }
    if (!FormCommands ())
      return;
    if (!FormScript ())
      return;  
    RunButton->Enable (false);
    Hide ();
    SimulationWindow = new Simulation(this, wxID_ANY, wxEmptyString);
    SimulationWindow->Enable (true);
    if (Apollo7CmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 7 Command Module"));
    else if (Colossus249Button->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 8 Command Module"));
    else if (Apollo9CmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 9 Command Module"));
    else if (Apollo9LmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 9 Lunar Module"));
    else if (Apollo10CmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 10 Command Module"));
    else if (Apollo10LmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 10 Lunar Module"));
    else if (Comanche55Button->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 11 Command Module"));
    else if (Luminary99Button->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 11 Lunar Module"));
    else if (Apollo12CmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 12 Command Module"));
    else if (Apollo12LmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 12 Lunar Module"));
    else if (Apollo13CmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 13 Command Module"));
    else if (Luminary131Button->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 13 Lunar Module"));
    else if (Apollo14CmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 14 Command Module"));
    else if (Apollo14LmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 14 Lunar Module"));
    else if (Artemis72Button->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 15-17 Command Module"));
    else if (Apollo15LmButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Apollo 15-17 Lunar Module"));
    else if (ValidationButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Validation Suite"));
    else if (AgcCustomButton->GetValue ())
      SimulationWindow->WriteSimulationLabel (wxT ("Custom Lunar Module"));
    else
      SimulationWindow->WriteSimulationLabel (wxT ("Unknown type of"));
    // Write the run-script contents to the detail pane of the window.
    wxString OutDummy, InDummy;
    wxTextFile Script;
    int i, Lines;
    OutDummy = wxT ("cd ") + ResourceDirectory;
#ifdef WIN32
    OutDummy += wxT ("\nsimulate2.bat");
    OutDummy += wxT ("\n\nThe contents of \"simulate2.bat\" are:");
    Script.Open (wxT ("simulate2.bat"));
    Lines = Script.GetLineCount ();
    for (i = 0; i < Lines; i++)
      {
        OutDummy += wxT ("\n");
	OutDummy += Script.GetLine (i);
      }
    Script.Close ();
    OutDummy += wxT ("\n\nThe contents of \"simulate.bat\" are:");
    Script.Open (wxT ("simulate.bat"));
#else
    OutDummy += wxT ("\n./simulate");
    OutDummy += wxT ("\n\nThe contents of \"simulate\" are:");
    Script.Open (wxT ("simulate"));
#endif
    Lines = Script.GetLineCount ();
    for (i = 0; i < Lines; i++)
      {
        OutDummy += wxT ("\n");
	OutDummy += Script.GetLine (i);
      }
    Script.Close ();
#ifdef WIN32
    OutDummy += wxT ("\n\nNote that WinAGC is used for the purpose of insuring that all simulated");
#else
    OutDummy += wxT ("\n\nNote that SimStop is used for the purpose of insuring that all simulated");
#endif
    OutDummy += wxT ("\ncomponents shut down after any one of them has shut down.  It does not");
    OutDummy += wxT ("\nin itself provide any simulation capabilities and might be unnecessary");
    OutDummy += wxT ("\noutside of the context of the VirtualAGC GUI.");
    SimulationWindow->ScriptText->SetValue (OutDummy);
    SimulationWindow->LessButton->Disable ();
    SimulationWindow->MoreButton->Enable ();
    SimulationWindow->DetailPanel->Hide ();
    SimulationWindow->Fit ();
    SimulationWindow->Show();
#ifdef WIN32
    wxString Command = wxT ("simulate2.bat");
#else    
    wxString Command = wxT ("./simulate");
#endif
    wxExecute (Command, wxEXEC_SYNC | wxEXEC_NODISABLE);
    SimulationWindow->Close ();
    delete SimulationWindow;
    Show ();
    RunButton->Enable (true);
}


void VirtualAGC::DefaultsButtonEvent(wxCommandEvent &event)
{
    TEMPTRACE ("25");
    SetDefaultConfiguration ();
    EnforceConsistency ();
}


void VirtualAGC::ExitButtonEvent(wxCommandEvent &event)
{
    TEMPTRACE ("26");
    EnforceConsistency ();
    WriteConfigurationFile ();
    Close ();
}


void VirtualAGC::AgcSourceEvent(wxCommandEvent &event)
{
  wxString Dummy;
  Dummy = wxT ("file://");
  Dummy += ResourceDirectory;
  Dummy += wxT ("/source/");
  if (Colossus249Button->GetValue ())
    Dummy += wxT ("Colossus249/Colossus249.html");
  else if (Luminary131Button->GetValue ())
    Dummy += wxT ("Luminary131/Luminary131.html");
  else if (ValidationButton->GetValue ())
    Dummy += wxT ("Validation/Validation.html");
  wxLaunchDefaultBrowser (Dummy);
}


void VirtualAGC::AeaSourceEvent(wxCommandEvent &event)
{
  wxString Dummy;
  Dummy = wxT ("file://");
  Dummy += ResourceDirectory;
  Dummy += wxT ("/source/");
  if (FlightProgram4Button->GetValue ())
    Dummy += wxT ("FP4/FP4.html");
  else if (FlightProgram5Button->GetValue ())
    Dummy += wxT ("FP5/FP5.html");
  else if (FlightProgram6Button->GetValue ())
    Dummy += wxT ("FP6/FP6.html");
  else if (FlightProgram7Button->GetValue ())
    Dummy += wxT ("FP7/FP7.html");
  else if (FlightProgram8Button->GetValue ())
    Dummy += wxT ("FP8/FP8.html");
  wxLaunchDefaultBrowser (Dummy);
}


void VirtualAGC::StartupWipeEvent(wxCommandEvent &event)
{
    TEMPTRACE ("27");
    EnforceConsistency ();
}


void VirtualAGC::StartupPreserveEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::StartupResumeEvent(wxCommandEvent &event)
{
    TEMPTRACE ("28");
    EnforceConsistency ();
}


void VirtualAGC::CustomCoreClick(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo7CmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Colossus249Event(wxCommandEvent &event)
{
    TEMPTRACE ("29");
    EnforceConsistency ();
}


void VirtualAGC::Apollo9CmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo9LmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo10CmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo10LmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Comanche55Event(wxCommandEvent &event)
{
    TEMPTRACE ("30");
    EnforceConsistency ();
}


void VirtualAGC::Luminary99Event(wxCommandEvent &event)
{
    TEMPTRACE ("31");
    EnforceConsistency ();
}


void VirtualAGC::Apollo12CmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo12LmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo13CmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Luminary131Event(wxCommandEvent &event)
{
    TEMPTRACE ("32");
    EnforceConsistency ();
}


void VirtualAGC::Apollo14CmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Apollo14LmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::Artemis72Event(wxCommandEvent &event)
{
    TEMPTRACE ("33");
    EnforceConsistency ();
}


void VirtualAGC::Apollo15LmEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::ValidationEvent(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::AgcCustomEvent(wxCommandEvent &event)
{
    TEMPTRACE ("34");
    EnforceConsistency ();
}


void VirtualAGC::FlightProgram4Event(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::FlightProgram5Event(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::FlightProgram6Event(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::FlightProgram7Event(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::FlightProgram8Event(wxCommandEvent &event)
{
    EnforceConsistency ();
}


void VirtualAGC::AeaCustomEvent(wxCommandEvent &event)
{
    TEMPTRACE ("34");
    EnforceConsistency ();
}


void VirtualAGC::DskyFullEvent(wxCommandEvent &event)
{
    TEMPTRACE ("35");
    EnforceConsistency ();
}


void VirtualAGC::DskyHalfEvent(wxCommandEvent &event)
{
    TEMPTRACE ("36");
    EnforceConsistency ();
}


void VirtualAGC::DskyLiteEvent(wxCommandEvent &event)
{
    TEMPTRACE ("37");
    EnforceConsistency ();
}


void VirtualAGC::AgcDebugNormalEvent(wxCommandEvent &event)
{
    TEMPTRACE ("38");
    EnforceConsistency ();
}


void VirtualAGC::AgcDebugMonitorEvent(wxCommandEvent &event)
{
    TEMPTRACE ("39");
    EnforceConsistency ();
}


void VirtualAGC::DedaFullEvent(wxCommandEvent &event)
{
    TEMPTRACE ("40");
    EnforceConsistency ();
}


void VirtualAGC::DedaHalfEvent(wxCommandEvent &event)
{
    TEMPTRACE ("41");
    EnforceConsistency ();
}


void VirtualAGC::AeaDebugNormalEvent(wxCommandEvent &event)
{
    TEMPTRACE ("42");
    EnforceConsistency ();
}


void VirtualAGC::AeaDebugMonitorEvent(wxCommandEvent &event)
{
    TEMPTRACE ("43");
    EnforceConsistency ();
}


// wxGlade: add VirtualAGC event handlers


void VirtualAGC::set_properties()
{
    // begin wxGlade: VirtualAGC::set_properties
    SetTitle(wxT("VirtualAGC Simulation Manager"));
    wxIcon _icon;
    _icon.CopyFromBitmap(wxBitmap(wxT("ApolloPatch2.png"), wxBITMAP_TYPE_ANY));
    SetIcon(_icon);
    SetBackgroundColour(wxColour(255, 255, 255));
    Patch1Bitmap->SetToolTip(wxT("This is the mission patch for the ill-fated Apollo 1 mission, which resulted in the deaths during a launch-pad test of astronauts Gus Grissom, Ed White, and Roger Chaffee."));
    Patch7Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 7, the first mission which actually launched.  It was an Earth-orbital CM-only mission without an LM.  The astronauts were Wally Schirra, Donn Eisele, and Walt Cunningham."));
    Patch8Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 8, which performed the famous lunar fly-by at Christmas in 1968.  It was a CM-only mission without an LM. The astronauts were Frank Borman, Jim Lovell, and Bill Anders."));
    Patch9Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 9, the first mission with an LM.  This was an Earth-orbital test.  The astronauts were Jim McDivitt, Dave Scott, and Rusty Schweikart."));
    Patch10Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 10, which was the first test of the LM in the lunar neighborhood (8.4 miles).  There must have been a great temptation to try to land, but the LM was slightly too heavy for this.  There was a mishap during the landing rehearsal in which control of the LM was temporarily compromised, but fortunately disaster was averted.  The astronauts were Tom Stafford, John Young, and Gene Cernan."));
    Patch11Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 11, the famous first landing.  A faulty checklist procedure caused the rendezvous radar to remain activated during the landing.  The unwanted and unexpected extra data overloaded the AGC and caused spurious warning messages that could have resulted in an abort.  Fortunately the design of the AGC software allowed the computer to work around this problem, though at reduced capacity, and thus the landing was not aborted.  However, there were only seconds of fuel left after touchdown. The mission patch is unique in that the astronauts' names do not appear on it.  The astronauts were, of course, Neil Armstrong, Buzz Aldrin, and Michael Collins."));
    Patch12Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 12.  The rocket was famously struck by lightning while still in Earth's atmosphere.  The astronauts were Pete Conrad, DickGordon, and Alan Bean."));
    Patch13Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 13.  As is well-known, outgassing of oxygen from a ruptured tank en route to the moon averted any possibility of a landing.  The crew instead had to spend the entire journey in the LM to conserve the precious resources of the CM for eventual re-entry, but fortunately survived the experience.  The astronauts were Jim Lovell, Jack Swigert, and Fred Haise.  Swigert was a last-minute replacement for Ken Mattingly, who later flew on Apollo 16."));
    Patch14Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 14.  The mission almost had an aborted landing due to a short-circuit sending faulty data to the AGC.  The astronauts were Alan Shepard, Stu Roosa, and Edgar Mitchell.  Shepard was the first American in space, but had flown no missions since then due to medical problems."));
    Patch15Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 15.  This was the first mission involving the lunar rover vehicle.  The astronauts were Dave Scott, Al Worden, and Jim Irwin."));
    Patch16Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 16.  The landing was nearly scrubbed because of a fault in the CM, but fortunately the landing took place.  The astronauts were Jim Young, Ken Mattingly, and Charles Duke."));
    Patch17Bitmap->SetToolTip(wxT("This is the mission patch for Apollo 17, the last moon landing in the Apollo program.  This was the only night launch in the Apollo program, and thus the only one which could be seen easily by large numbers of Americans.  It was also the first and only mission with a geologist aboard.  The astronauts were Gene Cernan, Ronald Evans, and Jack Schmitt.  Schmitt was the geologist and later a U.S. Senator."));
    SimTypeLabel->SetBackgroundColour(wxColour(255, 255, 255));
    SimTypeLabel->SetFont(wxFont(12, wxDEFAULT, wxNORMAL, wxBOLD, 1, wxT("")));
    SimTypeLabel->SetToolTip(wxT("In this area, you can select the Apollo mission and the spacecraft software version."));
    Apollo7CmButton->Enable(false);
    Colossus249Button->SetToolTip(wxT("Click this to run a simulation for the Apollo 8 CM from the first lunar fly-by.  This will use AGC software designated Colossus 1A (build 249, October 28, 1968)."));
    Colossus249Button->SetValue(1);
    Apollo9CmButton->Enable(false);
    Apollo9LmButton->Enable(false);
    Apollo10CmButton->Enable(false);
    Apollo10LmButton->Enable(false);
    Comanche55Button->SetToolTip(wxT("Click this to simulate the Apollo 11 CM from the FIRST moon landing.  This will run AGC software Colossus 2A, otherwise known as Comanche (rev. 55, 1 August 1969)."));
    Comanche55Button->Enable(false);
    Luminary99Button->SetToolTip(wxT("Click this to simulate the Apollo 11 LM from the FIRST moon landing.  This will run AGC software Luminary 1A (rev. 55, 14 July 1969)."));
    Luminary99Button->Enable(false);
    Apollo12CmButton->Enable(false);
    Apollo12LmButton->Enable(false);
    Apollo13CmButton->Enable(false);
    Luminary131Button->SetToolTip(wxT("Click this to simulate the ill-fated but nevertheless heroic Apollo 13 LM.  This will run AGC software Luminary 1C (rev. 131)."));
    Apollo14CmButton->Enable(false);
    Apollo14LmButton->Enable(false);
    Artemis72Button->SetToolTip(wxT("Click this to simulate the Apollo 15-17 CM, including the LAST moon-landing.  This will run AGC software Colossus 3, otherwise known as Artemis (rev. 072)."));
    Apollo15LmButton->Enable(false);
    AgcCustomButton->SetBackgroundColour(wxColour(255, 255, 255));
    AgcCustomButton->SetToolTip(wxT("Click here to run your own personal software creation on the AGC system.  You should first have compiled your assembly-language source code using the yaYUL program to create an executable binary."));
    AgcCustomFilename->SetBackgroundColour(wxColour(255, 255, 255));
    AgcCustomFilename->SetForegroundColour(wxColour(16, 16, 16));
    AgcCustomFilename->SetFont(wxFont(10, wxDEFAULT, wxNORMAL, wxNORMAL, 0, wxT("")));
    AgcCustomFilename->SetToolTip(wxT("If you wish to run guidance-computer software you have written yourself rather than actual mission software, you can put the filename here.  It must already have been compiled into binary executable format.  If you want to actually compile the software in addition, use the \"...\" button to the right."));
    AgcCustomFilename->Enable(false);
    AgcFilenameBrowse->SetMinSize(wxSize(40, 27));
    AgcFilenameBrowse->SetBackgroundColour(wxColour(240, 240, 240));
    AgcFilenameBrowse->SetToolTip(wxT("Click this button to select the name of the AGC runtime software using a file-selection dialog.  This can be either a pre-compiled binary, or it can be AGC assembly-language source code.  If the latter, then VirtualAGC will actually compile it for you using the yaYUL utility."));
    AgcFilenameBrowse->Enable(false);
    AgcSourceButton->SetToolTip(wxT("Click this to view the assembly listing (source code) for the selected AGC simulation type(s)."));
    AeaSourceButton->SetToolTip(wxT("Click this to view the selected AEA Flight Program assembly listing."));
    DeviceListLabel->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceListLabel->SetFont(wxFont(12, wxDEFAULT, wxNORMAL, wxBOLD, 1, wxT("")));
    DeviceListLabel->SetToolTip(wxT("In this area, you can select the particular computers and peripherals devices which will be simulated, along with the controls that will be displayed."));
    DeviceAgcCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceAgcCheckbox->SetToolTip(wxT("We assume that you will ALWAYS need to run the simulated guidance computer (AGC), so we don't allow you the option of deselecting it."));
    DeviceAgcCheckbox->Enable(false);
    DeviceAgcCheckbox->SetValue(1);
    DeviceDskyCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceDskyCheckbox->SetToolTip(wxT("We assume that you will ALWAYS need to run the simulated display/keypad (DSKY), so we don't allow you the option of deselecting it."));
    DeviceDskyCheckbox->Enable(false);
    DeviceDskyCheckbox->SetValue(1);
    DeviceAcaCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceAcaCheckbox->SetToolTip(wxT("The ACA is the rotational hand-controller (stick) used by the astronauts to control thrusters.  To use it, you must have a supported 3D joystick."));
    DeviceTelemetryCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceTelemetryCheckbox->SetToolTip(wxT("The telemetry downlink monitor displays information which the guidance computer continually transmits to mission control.  Unfortunately, it does not mimic the actual APPEARANCE of the display screens used in mission control, because nobody seems to know exactly how they looked."));
    DeviceAeaCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceAeaCheckbox->SetToolTip(wxT("The AEA (or sometimes AGS) is a completely separate computer system in the LM which could be used (but never was used in a real mission) in case of failure of the guidance computer, in order to abort."));
    DeviceDedaCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceDedaCheckbox->SetToolTip(wxT("The DEDA was the display/keyboard interface used for the LM abort computer (AEA)."));
    DeviceDedaCheckbox->Enable(false);
    DeviceCpumonCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceCpumonCheckbox->SetToolTip(wxT("This is the main window for the \"LM_simulator\" subsystem.  While designed for the LM and not yet adapted for the CM, it is of some use in CM simulations as well.  This particular window provides a continuous display of the state of the guidance computer's input/output channels.  It does not correspond to anything that actually existed in the spacecraft.  This needs to be selected in order to select any of the peripheral devices appearing below."));
    DeviceImuCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceImuCheckbox->SetToolTip(wxT("This is part of the \"LM_Simulator\" subsystem.  It is basically an interface to the Inertial Monitoring Unit (IMU).  It gives continuous feedback on the velocity and attitude of the spacecraft.  The FDAI (8-ball) provides a visual status of the pitch/yaw/roll.  "));
    DeviceImuCheckbox->Enable(false);
    DeviceDiscoutCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceDiscoutCheckbox->SetToolTip(wxT("This is part of the \"LM_Simulator\" subsystem.  It provides a visual indicator of the states of various discrete signals controlled by the guidance computer.  In the actual spacecraft, these signals were not all collected together into a single window like this."));
    DeviceDiscoutCheckbox->Enable(false);
    DeviceCrewinCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceCrewinCheckbox->SetToolTip(wxT("This is part of the \"LM_Simulator\" subsystem.  It provides a way to turn various signals on or off (as the crew would have done with switches or buttons) and to feed those signals to the guidance computer."));
    DeviceCrewinCheckbox->Enable(false);
    DeviceSysinCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DeviceSysinCheckbox->SetToolTip(wxT("This is part of the \"LM_Simulator\" subsystem.  It provides a way to set the states of various signals used as inputs to the guidance computer that would normally have been set by systems within the spacecraft that are not present in this simulation."));
    DeviceSysinCheckbox->Enable(false);
    DevicePropulsionCheckbox->SetBackgroundColour(wxColour(255, 255, 255));
    DevicePropulsionCheckbox->SetToolTip(wxT("This is part of the \"LM_Simulator\" subsystem.  It provides a continuous monitor of the spacecraft's fuel level, thrust, and so on.  The data is closely tied to the LM at this point, and is limited value in the CM."));
    DevicePropulsionCheckbox->Enable(false);
    NoviceButton->SetBackgroundColour(wxColour(240, 240, 240));
    NoviceButton->SetToolTip(wxT("Click this button to set the minimum reasonable combination of devices above without having to go through the list and select them or deselect them one-by-one."));
    ExpertButton->SetBackgroundColour(wxColour(240, 240, 240));
    ExpertButton->SetToolTip(wxT("Click this button to set the maximum reasonable combination of devices above, given the simulation type being run, without having to go through the list and select them or deselect them one-by-one."));
    FlightProgram4Button->SetBackgroundColour(wxColour(255, 255, 255));
    FlightProgram4Button->SetToolTip(wxT("Click this to simulate the Apollo 9 LM for the first orbital test of the LM.  This will run the AEA/AGS software designated as Flight Program 3 or 4."));
    FlightProgram4Button->Enable(false);
    FlightProgram5Button->SetBackgroundColour(wxColour(255, 255, 255));
    FlightProgram5Button->SetToolTip(wxT("Click this to simulate the Apollo 10 LM, which was the first LM test in the lunar neighborhood.  The Apollo 10 mission experienced a mishap associated with the AGC and AEA both trying to control the LM simultaneously.  This will run the AEA/AGS software designated as Flight Program 5."));
    FlightProgram5Button->Enable(false);
    FlightProgram6Button->SetBackgroundColour(wxColour(255, 255, 255));
    FlightProgram6Button->SetToolTip(wxT("Click this to simulate the Apollo 11 LM for the FIRST moon landing.  This will run the AEA/AGS software designated as Flight Program 6 (June 1969)."));
    FlightProgram6Button->SetValue(1);
    FlightProgram7Button->SetBackgroundColour(wxColour(255, 255, 255));
    FlightProgram7Button->SetToolTip(wxT("Click this to simulate the Apollo 12-14 LM ... maybe.  We're not actually sure which missions were associated with this software version.  This will run the AEA/AGS software designated as Flight Program 7."));
    FlightProgram7Button->Enable(false);
    FlightProgram8Button->SetBackgroundColour(wxColour(255, 255, 255));
    FlightProgram8Button->SetToolTip(wxT("Click this to simulate the Apollo 15-17 LM.  This will run the AEA/AGS software designated as Flight Program 8 (December 1970)."));
    AeaCustomButton->SetBackgroundColour(wxColour(255, 255, 255));
    AeaCustomButton->SetToolTip(wxT("Click here to run your own personal software creation on the AEA/AGS system.  You should first have compiled your assembly-language source code using the yaLEMAP program to create an executable binary."));
    AeaCustomFilename->SetBackgroundColour(wxColour(255, 255, 255));
    AeaCustomFilename->SetForegroundColour(wxColour(16, 16, 16));
    AeaCustomFilename->SetToolTip(wxT("If you wish to run abort-computer software you have written yourself rather than actual mission software, you can put the filename here.  It must already have been compiled into binary executable format.  If you want to actually compile the software in addition, use the \"...\" button to the right."));
    AeaCustomFilename->Enable(false);
    AeaFilenameBrowse->SetMinSize(wxSize(40, 27));
    AeaFilenameBrowse->SetBackgroundColour(wxColour(240, 240, 240));
    AeaFilenameBrowse->SetToolTip(wxT("Click this button to select the name of the AEA runtime software using a file-selection dialog.  This can be either a pre-compiled binary, or it can be AEA assembly-language source code.  If the latter, then VirtualAGC will actually compile it for you using the yaLEMAP utility."));
    AeaFilenameBrowse->Enable(false);
    OptionList->SetBackgroundColour(wxColour(255, 255, 255));
    OptionList->SetFont(wxFont(12, wxDEFAULT, wxNORMAL, wxBOLD, 1, wxT("")));
    OptionList->SetToolTip(wxT("In this area, you can select various infrequently-used options that can assist in special purposes."));
    StartupWipeButton->SetToolTip(wxT("The magnetic-core memory of the AGC is \"persistent\", meaning that it retains its memory when power is off, and hence can resume the computer program after power-up that it was running before shutdown.  If you would prefer NOT to resume and instead to start with completely erased memory, then choose this option."));
    StartupWipeButton->SetValue(1);
    StartupPreserveButton->SetToolTip(wxT("Choose this to restart the program on startup, but otherwise preserving the contents of volatile memory."));
    StartupResumeButton->SetToolTip(wxT("The magnetic-core memory of the AGC is \"persistent\", meaning that it retains its memory when power is off, and hence can resume the computer program after power-up that it was running before shutdown.  If you would like to do that, then choose this option."));
    CustomResumeButton->SetToolTip(wxT("Select a custom memory-core file from which to resume operation."));
    CoreFilename->SetBackgroundColour(wxColour(255, 255, 255));
    CoreFilename->Enable(false);
    CoreBrowse->SetMinSize(wxSize(40, 27));
    CoreBrowse->SetBackgroundColour(wxColour(240, 240, 240));
    CoreBrowse->SetToolTip(wxT("Click this button to select the name of an AGC core dump from which to resume execution."));
    CoreBrowse->Enable(false);
    CoreSaveButton->SetMinSize(wxSize(42, 27));
    CoreSaveButton->SetBackgroundColour(wxColour(240, 240, 240));
    CoreSaveButton->SetToolTip(wxT("Click this button to preserve the most-recent core-dump so that you can resume operation from it later, by name."));
    DskyFullButton->SetToolTip(wxT("This is the default display/keypad simulation."));
    DskyFullButton->SetValue(1);
    DskyHalfButton->SetToolTip(wxT("Using a half-size display/keypad simulation can be useful if you don't have much space on your display-screen."));
    DskyLiteButton->SetToolTip(wxT("The DSKY Lite is an alternate simulation of the display/keypad unit, using software contributed by Stephan Hotto.  There may be some circumstances under which you would find it useful.  However, it can only be used if in the \"Devices\" menu you select \"AGC CPU Bus/Input/Output Monitor\" and DO NOT select \"Telemetry Downlink Monitor\"."));
    TelemetryResizable->SetToolTip(wxT("Uses a format for the telemetry display in which the text size and display size is adjustable."));
    TelemetryResizable->SetValue(1);
    TelemetryRetro->SetToolTip(wxT("The telemetry-display has a \"retro\" appearance, in which it looks somewhat like it's a CRT such as those from mission control.  However, it is not resizable and consumes quite a lot of space on your computer's actual display."));
    AgcDebugNormalButton->SetToolTip(wxT("Click this to run the simulated AGC CPU in the normal manner."));
    AgcDebugNormalButton->SetValue(1);
    AgcDebugMonitorButton->SetToolTip(wxT("Click this to run the simulated AGC CPU with a debug monitor that allows single-stepping, breakpoints, disassembly, dumping/editing of memory, etc."));
    DedaFullButton->SetToolTip(wxT("This is the default AEA display/keypad simulation."));
    DedaFullButton->SetValue(1);
    DedaHalfButton->SetToolTip(wxT("The half-size DEDA simulation can be useful if you have limited free space on your display screen."));
    AeaDebugNormalButton->SetToolTip(wxT("This is the normal manner of simulating the AEA/AGS."));
    AeaDebugNormalButton->SetValue(1);
    AeaDebugMonitorButton->SetToolTip(wxT("Click this to run the simulated AEA/AGS CPU with a debug monitor that allows single-stepping, breakpoints, disassembly, dumping/editing of memory, etc."));
    RunButton->SetBackgroundColour(wxColour(240, 240, 240));
    RunButton->SetToolTip(wxT("Click this button to begin running the simulation using all of the various options and settings selected above!"));
    DefaultsButton->SetBackgroundColour(wxColour(240, 240, 240));
    DefaultsButton->SetToolTip(wxT("When you change the various settings above, they are persistent.  In other words, if you run this program again, the settings will be whatever you set them at in the prior run.  If you click this button, it will return the settings to the defaults that existed when this program was first installed."));
    ExitButton->SetBackgroundColour(wxColour(240, 240, 240));
    ExitButton->SetToolTip(wxT("Click this button to exit this program.  Your settings will be saved."));
    // end wxGlade
}


void VirtualAGC::do_layout()
{
    // begin wxGlade: VirtualAGC::do_layout
    wxBoxSizer* TopSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_3 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_2 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_8 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_9 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_10 = new wxBoxSizer(wxVERTICAL);
    wxStaticBoxSizer* sizer_23 = new wxStaticBoxSizer(sizer_23_staticbox, wxVERTICAL);
    wxStaticBoxSizer* sizer_24 = new wxStaticBoxSizer(sizer_24_staticbox, wxVERTICAL);
    wxStaticBoxSizer* sizer_22 = new wxStaticBoxSizer(sizer_22_staticbox, wxVERTICAL);
    wxStaticBoxSizer* sizer_28 = new wxStaticBoxSizer(sizer_28_staticbox, wxVERTICAL);
    wxStaticBoxSizer* sizer_21 = new wxStaticBoxSizer(sizer_21_staticbox, wxVERTICAL);
    wxStaticBoxSizer* sizer_18 = new wxStaticBoxSizer(sizer_18_staticbox, wxVERTICAL);
    wxBoxSizer* sizer_34 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_5 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_29 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_30 = new wxBoxSizer(wxVERTICAL);
    wxStaticBoxSizer* sizer_20 = new wxStaticBoxSizer(sizer_20_staticbox, wxVERTICAL);
    wxBoxSizer* sizer_15_copy = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_6 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_7 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_12 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_35 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_36 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_4 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_1 = new wxBoxSizer(wxHORIZONTAL);
    wxStaticBoxSizer* sizer_1_copy = new wxStaticBoxSizer(sizer_1_copy_staticbox, wxHORIZONTAL);
    wxBoxSizer* sizer_11 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_13 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_14 = new wxBoxSizer(wxVERTICAL);
    wxStaticBoxSizer* sizer_19 = new wxStaticBoxSizer(sizer_19_staticbox, wxVERTICAL);
    wxBoxSizer* sizer_15 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* HeaderSizer = new wxBoxSizer(wxHORIZONTAL);
    wxGridSizer* RightSizer = new wxGridSizer(1, 6, 0, 0);
    wxBoxSizer* MiddleSizer = new wxBoxSizer(wxHORIZONTAL);
    wxGridSizer* LeftSizer = new wxGridSizer(1, 6, 0, 0);
    TopSizer->Add(20, 5, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    LeftSizer->Add(Patch1Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    LeftSizer->Add(Patch7Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    LeftSizer->Add(Patch8Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    LeftSizer->Add(Patch9Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    LeftSizer->Add(Patch10Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    LeftSizer->Add(Patch11Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    HeaderSizer->Add(LeftSizer, 1, wxEXPAND, 0);
    MiddleSizer->Add(20, 20, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    MiddleSizer->Add(PatchBitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    MiddleSizer->Add(20, 20, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    HeaderSizer->Add(MiddleSizer, 1, wxEXPAND, 0);
    RightSizer->Add(Patch12Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    RightSizer->Add(Patch13Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    RightSizer->Add(Patch14Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    RightSizer->Add(Patch15Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    RightSizer->Add(Patch16Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    RightSizer->Add(Patch17Bitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    HeaderSizer->Add(RightSizer, 1, wxEXPAND, 0);
    TopSizer->Add(HeaderSizer, 0, wxEXPAND, 0);
    TopSizer->Add(20, 5, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    TopSizer->Add(TopLine, 0, wxEXPAND, 0);
    sizer_4->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_4->Add(SimTypeLabel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_4->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_11->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_19->Add(Apollo7CmButton, 0, 0, 0);
    sizer_19->Add(Colossus249Button, 0, 0, 0);
    sizer_19->Add(Apollo9CmButton, 0, 0, 0);
    sizer_19->Add(Apollo9LmButton, 0, 0, 0);
    sizer_19->Add(Apollo10CmButton, 0, 0, 0);
    sizer_19->Add(Apollo10LmButton, 0, 0, 0);
    sizer_19->Add(Comanche55Button, 0, 0, 0);
    sizer_19->Add(Luminary99Button, 0, 0, 0);
    sizer_19->Add(Apollo12CmButton, 0, 0, 0);
    sizer_19->Add(Apollo12LmButton, 0, 0, 0);
    sizer_19->Add(Apollo13CmButton, 0, 0, 0);
    sizer_19->Add(Luminary131Button, 0, 0, 0);
    sizer_19->Add(Apollo14CmButton, 0, 0, 0);
    sizer_19->Add(Apollo14LmButton, 0, 0, 0);
    sizer_19->Add(Artemis72Button, 0, 0, 0);
    sizer_19->Add(Apollo15LmButton, 0, 0, 0);
    sizer_19->Add(ValidationButton, 0, 0, 0);
    sizer_15->Add(AgcCustomButton, 0, 0, 0);
    sizer_15->Add(AgcCustomFilename, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
    sizer_15->Add(AgcFilenameBrowse, 0, 0, 0);
    sizer_19->Add(sizer_15, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_14->Add(sizer_19, 1, wxEXPAND, 0);
    sizer_14->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_13->Add(sizer_14, 1, wxEXPAND, 0);
    sizer_11->Add(sizer_13, 1, wxEXPAND, 0);
    sizer_11->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_4->Add(sizer_11, 0, wxEXPAND, 0);
    sizer_1->Add(20, 20, 0, 0, 0);
    sizer_1_copy->Add(20, 20, 1, 0, 0);
    sizer_1_copy->Add(AgcSourceButton, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_1_copy->Add(20, 20, 0, 0, 0);
    sizer_1_copy->Add(AeaSourceButton, 0, 0, 0);
    sizer_1_copy->Add(20, 20, 1, 0, 0);
    sizer_1->Add(sizer_1_copy, 1, wxEXPAND, 0);
    sizer_1->Add(20, 20, 0, 0, 0);
    sizer_4->Add(sizer_1, 0, wxEXPAND, 0);
    sizer_4->Add(20, 10, 0, 0, 0);
    sizer_2->Add(sizer_4, 1, wxEXPAND, 0);
    sizer_2->Add(static_line_2, 0, wxEXPAND, 0);
    sizer_5->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_5->Add(DeviceListLabel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_5->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_6->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_7->Add(DeviceAgcCheckbox, 0, 0, 0);
    sizer_7->Add(DeviceDskyCheckbox, 0, 0, 0);
    sizer_7->Add(DeviceAcaCheckbox, 0, 0, 0);
    sizer_7->Add(DeviceTelemetryCheckbox, 0, 0, 0);
    sizer_7->Add(DeviceAeaCheckbox, 0, 0, 0);
    sizer_7->Add(DeviceDedaCheckbox, 0, 0, 0);
    sizer_7->Add(DeviceCpumonCheckbox, 0, 0, 0);
    sizer_35->Add(static_line_4, 1, wxEXPAND, 0);
    sizer_36->Add(DeviceImuCheckbox, 0, 0, 0);
    sizer_36->Add(DeviceDiscoutCheckbox, 0, 0, 0);
    sizer_36->Add(DeviceCrewinCheckbox, 0, 0, 0);
    sizer_36->Add(DeviceSysinCheckbox, 0, 0, 0);
    sizer_36->Add(DevicePropulsionCheckbox, 0, 0, 0);
    sizer_35->Add(sizer_36, 15, wxEXPAND, 0);
    sizer_7->Add(sizer_35, 1, wxEXPAND, 0);
    sizer_7->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_12->Add(NoviceButton, 0, 0, 2);
    sizer_12->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_12->Add(ExpertButton, 0, 0, 0);
    sizer_7->Add(sizer_12, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_6->Add(sizer_7, 1, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_6->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_5->Add(sizer_6, 0, wxEXPAND, 0);
    sizer_5->Add(20, 20, 0, wxEXPAND, 0);
    sizer_29->Add(20, 20, 0, 0, 0);
    sizer_20->Add(FlightProgram4Button, 0, 0, 0);
    sizer_20->Add(FlightProgram5Button, 0, 0, 0);
    sizer_20->Add(FlightProgram6Button, 0, 0, 0);
    sizer_20->Add(FlightProgram7Button, 0, 0, 0);
    sizer_20->Add(FlightProgram8Button, 0, 0, 0);
    sizer_15_copy->Add(AeaCustomButton, 0, 0, 0);
    sizer_15_copy->Add(AeaCustomFilename, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
    sizer_15_copy->Add(AeaFilenameBrowse, 0, 0, 0);
    sizer_20->Add(sizer_15_copy, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_30->Add(sizer_20, 0, wxEXPAND, 0);
    sizer_29->Add(sizer_30, 1, wxEXPAND, 0);
    sizer_29->Add(20, 20, 0, 0, 0);
    sizer_5->Add(sizer_29, 0, wxEXPAND, 0);
    sizer_5->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_2->Add(sizer_5, 1, wxEXPAND, 0);
    sizer_2->Add(static_line_3, 0, wxEXPAND, 0);
    sizer_8->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_8->Add(OptionList, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_8->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_9->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_18->Add(StartupWipeButton, 0, 0, 0);
    sizer_18->Add(StartupPreserveButton, 0, 0, 0);
    sizer_18->Add(StartupResumeButton, 0, 0, 0);
    sizer_34->Add(CustomResumeButton, 0, 0, 0);
    sizer_34->Add(CoreFilename, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
    sizer_34->Add(CoreBrowse, 0, 0, 0);
    sizer_34->Add(CoreSaveButton, 0, 0, 0);
    sizer_18->Add(sizer_34, 1, wxEXPAND, 0);
    sizer_10->Add(sizer_18, 0, wxEXPAND, 0);
    sizer_10->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_21->Add(DskyFullButton, 0, 0, 0);
    sizer_21->Add(DskyHalfButton, 0, 0, 0);
    sizer_21->Add(DskyLiteButton, 0, 0, 0);
    sizer_10->Add(sizer_21, 0, wxEXPAND, 0);
    sizer_10->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_28->Add(TelemetryResizable, 0, 0, 0);
    sizer_28->Add(TelemetryRetro, 0, 0, 0);
    sizer_10->Add(sizer_28, 1, wxEXPAND, 0);
    sizer_10->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_22->Add(AgcDebugNormalButton, 0, 0, 0);
    sizer_22->Add(AgcDebugMonitorButton, 0, 0, 0);
    sizer_10->Add(sizer_22, 1, wxEXPAND, 0);
    sizer_10->Add(20, 10, 0, wxEXPAND, 0);
    sizer_24->Add(DedaFullButton, 0, 0, 0);
    sizer_24->Add(DedaHalfButton, 0, 0, 0);
    sizer_10->Add(sizer_24, 1, wxEXPAND, 0);
    sizer_10->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_23->Add(AeaDebugNormalButton, 0, 0, 0);
    sizer_23->Add(AeaDebugMonitorButton, 0, 0, 0);
    sizer_10->Add(sizer_23, 1, wxEXPAND, 0);
    sizer_10->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    sizer_9->Add(sizer_10, 1, 0, 0);
    sizer_9->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_8->Add(sizer_9, 0, wxEXPAND, 0);
    sizer_2->Add(sizer_8, 1, wxEXPAND, 0);
    TopSizer->Add(sizer_2, 0, wxEXPAND, 0);
    TopSizer->Add(static_line_1, 0, wxEXPAND, 0);
    TopSizer->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_3->Add(RunButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_3->Add(40, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_3->Add(DefaultsButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_3->Add(40, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_3->Add(ExitButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    TopSizer->Add(sizer_3, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    TopSizer->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    SetSizer(TopSizer);
    TopSizer->Fit(this);
    Layout();
    // end wxGlade
}



class VirtualAgcApp: public wxApp {
public:
    bool OnInit();
};

IMPLEMENT_APP(VirtualAgcApp)

static VirtualAGC *MainFrame;
bool VirtualAgcApp::OnInit()
{
    wxInitAllImageHandlers();
    //if (argc > 1)
    //  wxMessageBox (wxT ("Arguments!"));
    MainFrame = new VirtualAGC(NULL, wxID_ANY, wxEmptyString);
    SetTopWindow(MainFrame);
    MainFrame->Show();
    return true;
}

///////////////////////////////////////////////////////////////////////////////////////
// Various Auxiliary functions needed by the stuff above.

void
VirtualAGC::EnableRunButton (void)
{
  RunButton->Enable (true);
  Show (true);
}

// This function checks the enabling/disabling of all controls, and makes sure that 
// they are consistent among themselves.
void
VirtualAGC::EnforceConsistency (void)
{
  bool IsCustom = false;
  
  IsLM = Apollo9LmButton->GetValue () || Apollo10LmButton->GetValue () ||
         Luminary99Button->GetValue () || Apollo12LmButton->GetValue () ||
	 Luminary131Button->GetValue () || Apollo14LmButton->GetValue () ||
	 Apollo15LmButton->GetValue () || AgcCustomButton->GetValue ();
  IsCustom = AgcCustomButton->GetValue ();
  EnableLM (IsLM);
  EnableCustomAGC (IsCustom);
  DeviceTelemetryCheckbox->Enable (!ValidationButton->GetValue ());
  if (!DeviceTelemetryCheckbox->IsEnabled ())
    DeviceTelemetryCheckbox->SetValue (false);
  //if (DeviceTelemetryCheckbox->GetValue () && DskyLiteButton->GetValue ())
  //  DskyFullButton->SetValue (true);
  DeviceCpumonCheckbox->Enable (!ValidationButton->GetValue ());
  if (!DeviceCpumonCheckbox->IsEnabled ())
    DeviceCpumonCheckbox->SetValue (false);
  if (!DeviceCpumonCheckbox->GetValue ())
    {
      if (DskyLiteButton->GetValue ())
	DskyFullButton->SetValue (true);
      DeviceImuCheckbox->Enable (false);
      DeviceDiscoutCheckbox->Enable (false);
      DeviceCrewinCheckbox->Enable (false);
      DeviceSysinCheckbox->Enable (false);
      DevicePropulsionCheckbox->Enable (false);
    }
  if (!DeviceAcaCheckbox->IsEnabled ())
    DeviceAcaCheckbox->SetValue (false);
  if (!DeviceAeaCheckbox->IsEnabled ())
    {
      DeviceAeaCheckbox->SetValue (false);
      DeviceDedaCheckbox->SetValue (false);
    }
  if (!DeviceImuCheckbox->IsEnabled ())
    DeviceImuCheckbox->SetValue (false);
  if (!DeviceDiscoutCheckbox->IsEnabled ())
    DeviceDiscoutCheckbox->SetValue (false);
  if (!DeviceCrewinCheckbox->IsEnabled ())
    DeviceCrewinCheckbox->SetValue (false);
  if (!DeviceSysinCheckbox->IsEnabled ())
    DeviceSysinCheckbox->SetValue (false);
  if (!DevicePropulsionCheckbox->IsEnabled ())
    DevicePropulsionCheckbox->SetValue (false);
  DskyLiteButton->Enable (DeviceCpumonCheckbox->GetValue () /* && !DeviceTelemetryCheckbox->GetValue () */);  
  TelemetryResizable->Enable (DeviceTelemetryCheckbox->GetValue ());
  TelemetryRetro->Enable (DeviceTelemetryCheckbox->GetValue ());
  AgcSourceButton->Enable (Colossus249Button->GetValue () || 
  			   Luminary131Button->GetValue () ||
  			   ValidationButton->GetValue ());
  AeaSourceButton->Enable ((FlightProgram6Button->IsEnabled () && FlightProgram6Button->GetValue ()) ||
			   (FlightProgram8Button->IsEnabled () && FlightProgram8Button->GetValue ()));
  CoreFilename->Enable (CustomResumeButton->GetValue ());
  CoreBrowse->Enable (CustomResumeButton->GetValue ());
}

// This function goes through and either enables or disables all of the LM controls.
void 
VirtualAGC::EnableLM (bool YesNo)
{
  DeviceAcaCheckbox->Enable (YesNo);
  DeviceAeaCheckbox->Enable (YesNo);
  DeviceDedaCheckbox->SetValue (DeviceAeaCheckbox->GetValue ());
  EnableAEA (YesNo && DeviceAeaCheckbox->GetValue ());
  EnableCpumon (YesNo && DeviceCpumonCheckbox->GetValue ());
}

// This function goes through and either enables or disables all of the AEA controls.
void 
VirtualAGC::EnableAEA (bool YesNo)
{
  FlightProgram6Button->Enable (YesNo);
  FlightProgram8Button->Enable (YesNo);
  AeaCustomButton->Enable (YesNo);
  EnableCustomAEA (YesNo && AeaCustomButton->GetValue ());
  DeviceDedaCheckbox->Enable (false);
  EnableDEDA (YesNo && DeviceDedaCheckbox->GetValue ());
  AeaDebugNormalButton->Enable (YesNo);
  AeaDebugMonitorButton->Enable (YesNo);
}

// This function either enables or disables the DEDA controls
void
VirtualAGC::EnableDEDA (bool YesNo)
{
  DedaFullButton->Enable (YesNo);
  DedaHalfButton->Enable (YesNo);
}

// This function either enables or disables the AGC custom-program controls
void
VirtualAGC::EnableCustomAGC (bool YesNo)
{
  //AgcFilenameLabel->Enable (YesNo);
  AgcCustomFilename->Enable (YesNo);
  AgcFilenameBrowse->Enable (YesNo);
}

// This function either enables or disables the AEA custom-program controls
void
VirtualAGC::EnableCustomAEA (bool YesNo)
{
  //AeaFilenameLabel->Enable (YesNo);
  AeaCustomFilename->Enable (YesNo);
  AeaFilenameBrowse->Enable (YesNo);
}

// This function either enables or disables the LM-Simulator controls
void
VirtualAGC::EnableCpumon (bool YesNo)
{
  DeviceImuCheckbox->Enable (YesNo);
  DeviceDiscoutCheckbox->Enable (YesNo);
  DeviceCrewinCheckbox->Enable (YesNo);
  DeviceSysinCheckbox->Enable (YesNo);
  DevicePropulsionCheckbox->Enable (YesNo);
}


// Sets all of the settings to a reasonable default configuration.
void
VirtualAGC::SetDefaultConfiguration (void)
{
  Luminary131Button->SetValue (true);
  AgcCustomFilename->SetValue (wxT (""));
  FlightProgram6Button->SetValue (true);
  AeaCustomFilename->SetValue (wxT (""));
  DeviceAgcCheckbox->SetValue (true);
  DeviceDskyCheckbox->SetValue (true);
  DeviceAcaCheckbox->SetValue (false);
  DeviceTelemetryCheckbox->SetValue (true);
  DeviceAeaCheckbox->SetValue (false);
  DeviceDedaCheckbox->SetValue (false);
  DeviceCpumonCheckbox->SetValue (false);
  DeviceImuCheckbox->SetValue (false);
  DeviceDiscoutCheckbox->SetValue (false);
  DeviceCrewinCheckbox->SetValue (false);
  DeviceSysinCheckbox->SetValue (false);
  DevicePropulsionCheckbox->SetValue (false);
  StartupWipeButton->SetValue (true);
  AgcDebugNormalButton->SetValue (true);
  if (Points >= StartingPoints)
    {
      DedaFullButton->SetValue (true);
      DskyFullButton->SetValue (true);
    }
  else
    {
      DedaHalfButton->SetValue (true);
      DskyHalfButton->SetValue (true);
    }
  AeaDebugNormalButton->SetValue (true);
  TelemetryResizable->SetValue (true);
}

// Reads a configuration file to get all of the settings.

#define CHECK_TEXT_SETTING(name) \
  if (!Skip && Name.IsSameAs (wxT (#name))) \
    { \
      Skip = true; \
      name->SetValue (Value); \
    }

#define CHECK_TRUE_FALSE_SETTING(name) \
  if (!Skip && Name.IsSameAs (wxT (#name))) \
    { \
      Skip = true; \
      if (Value.IsSameAs (wxT ("true"))) \
        name->SetValue (true); \
      else \
        name->SetValue (false); \
    }

void
VirtualAGC::ReadConfigurationFile (void)
{
  wxTextFile Fin;
  if (wxFileExists (wxT ("VirtualAGC.cfg")))
    {
      if (Fin.Open (wxT ("VirtualAGC.cfg")))
	{
	  int i, NumLines = Fin.GetLineCount ();
	  for (i = 0; i < NumLines; i++)
	    {
	      wxString Line, Name, Value;
      	      bool Skip = false;
	      Line = Fin.GetLine (i);
	      Name = Line.BeforeFirst ('=');
	      Value = Line.AfterFirst ('=');
	      CHECK_TEXT_SETTING (AgcCustomFilename);
	      CHECK_TEXT_SETTING (AeaCustomFilename);
	      CHECK_TEXT_SETTING (CoreFilename);
	      CHECK_TRUE_FALSE_SETTING (Apollo7CmButton);
	      CHECK_TRUE_FALSE_SETTING (Colossus249Button);
	      CHECK_TRUE_FALSE_SETTING (Apollo9CmButton);
	      CHECK_TRUE_FALSE_SETTING (Apollo9LmButton);
	      CHECK_TRUE_FALSE_SETTING (Apollo10CmButton);
	      CHECK_TRUE_FALSE_SETTING (Apollo10LmButton);
	      CHECK_TRUE_FALSE_SETTING (Comanche55Button);
	      CHECK_TRUE_FALSE_SETTING (Luminary99Button);
	      CHECK_TRUE_FALSE_SETTING (Apollo12CmButton);
	      CHECK_TRUE_FALSE_SETTING (Apollo12LmButton);
	      CHECK_TRUE_FALSE_SETTING (Apollo13CmButton);
	      CHECK_TRUE_FALSE_SETTING (Luminary131Button);
	      CHECK_TRUE_FALSE_SETTING (Apollo14CmButton);
	      CHECK_TRUE_FALSE_SETTING (Apollo14LmButton);
	      CHECK_TRUE_FALSE_SETTING (Artemis72Button);
	      CHECK_TRUE_FALSE_SETTING (Apollo15LmButton);
	      CHECK_TRUE_FALSE_SETTING (ValidationButton);
	      CHECK_TRUE_FALSE_SETTING (AgcCustomButton);
	      CHECK_TRUE_FALSE_SETTING (FlightProgram4Button);
	      CHECK_TRUE_FALSE_SETTING (FlightProgram5Button);
	      CHECK_TRUE_FALSE_SETTING (FlightProgram6Button);
	      CHECK_TRUE_FALSE_SETTING (FlightProgram7Button);
	      CHECK_TRUE_FALSE_SETTING (FlightProgram8Button);
	      CHECK_TRUE_FALSE_SETTING (AeaCustomButton);
	      CHECK_TRUE_FALSE_SETTING (DeviceAgcCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceDskyCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceAcaCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceTelemetryCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceAeaCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceDedaCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceCpumonCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceImuCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceDiscoutCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceCrewinCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DeviceSysinCheckbox);
	      CHECK_TRUE_FALSE_SETTING (DevicePropulsionCheckbox);
	      CHECK_TRUE_FALSE_SETTING (StartupWipeButton);
	      CHECK_TRUE_FALSE_SETTING (StartupPreserveButton);
	      CHECK_TRUE_FALSE_SETTING (StartupResumeButton);
	      CHECK_TRUE_FALSE_SETTING (CustomResumeButton);
	      CHECK_TRUE_FALSE_SETTING (DskyFullButton);
	      CHECK_TRUE_FALSE_SETTING (DskyHalfButton);
	      CHECK_TRUE_FALSE_SETTING (DskyLiteButton);
	      CHECK_TRUE_FALSE_SETTING (AgcDebugNormalButton);
	      CHECK_TRUE_FALSE_SETTING (AgcDebugMonitorButton);
	      CHECK_TRUE_FALSE_SETTING (DedaFullButton);
	      CHECK_TRUE_FALSE_SETTING (DedaHalfButton);
	      CHECK_TRUE_FALSE_SETTING (AeaDebugNormalButton);
	      CHECK_TRUE_FALSE_SETTING (AeaDebugMonitorButton);
	      CHECK_TRUE_FALSE_SETTING (TelemetryResizable);
	      CHECK_TRUE_FALSE_SETTING (TelemetryRetro);
	    }
	  Fin.Close ();
	}
      else
	{
	  wxMessageBox (wxT ("Cannot open VirtualAGC.cfg.\nDefault configuration used!"), wxT ("Warning"), wxOK | wxICON_HAND);
	}
    }
}

// Writes a configuration file of all the settings.

#define WRITE_TRUE_FALSE_SETTING(name) \
  Fout.Write (wxT (#name)); \
  Fout.Write (wxT ("=")); \
  if (name->GetValue ()) \
    Fout.Write (wxT ("true")); \
  else \
    Fout.Write (wxT ("false")); \
  Fout.Write (wxT ("\n"))

#define WRITE_TEXT_SETTING(name) \
  Fout.Write (wxT (#name)); \
  Fout.Write (wxT ("=")); \
  Fout.Write (name->GetValue ()); \
  Fout.Write (wxT ("\n"))

void
VirtualAGC::WriteConfigurationFile (void)
{
  wxFile Fout;
  if (Fout.Create (wxT ("VirtualAGC.cfg"), true))
    {
      WRITE_TEXT_SETTING (AgcCustomFilename);
      WRITE_TEXT_SETTING (AeaCustomFilename);
      WRITE_TEXT_SETTING (CoreFilename);
      WRITE_TRUE_FALSE_SETTING (Apollo7CmButton);
      WRITE_TRUE_FALSE_SETTING (Colossus249Button);
      WRITE_TRUE_FALSE_SETTING (Apollo9CmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo9LmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo10CmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo10LmButton);
      WRITE_TRUE_FALSE_SETTING (Comanche55Button);
      WRITE_TRUE_FALSE_SETTING (Luminary99Button);
      WRITE_TRUE_FALSE_SETTING (Apollo12CmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo12LmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo13CmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo15LmButton);
      WRITE_TRUE_FALSE_SETTING (Luminary131Button);
      WRITE_TRUE_FALSE_SETTING (Apollo14CmButton);
      WRITE_TRUE_FALSE_SETTING (Apollo14LmButton);
      WRITE_TRUE_FALSE_SETTING (Artemis72Button);
      WRITE_TRUE_FALSE_SETTING (Apollo15LmButton);
      WRITE_TRUE_FALSE_SETTING (ValidationButton);
      WRITE_TRUE_FALSE_SETTING (AgcCustomButton);
      WRITE_TRUE_FALSE_SETTING (FlightProgram4Button);
      WRITE_TRUE_FALSE_SETTING (FlightProgram5Button);
      WRITE_TRUE_FALSE_SETTING (FlightProgram6Button);
      WRITE_TRUE_FALSE_SETTING (FlightProgram7Button);
      WRITE_TRUE_FALSE_SETTING (FlightProgram8Button);
      WRITE_TRUE_FALSE_SETTING (AeaCustomButton);
      WRITE_TRUE_FALSE_SETTING (DeviceAgcCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceDskyCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceAcaCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceTelemetryCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceAeaCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceDedaCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceCpumonCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceImuCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceDiscoutCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceCrewinCheckbox);
      WRITE_TRUE_FALSE_SETTING (DeviceSysinCheckbox);
      WRITE_TRUE_FALSE_SETTING (DevicePropulsionCheckbox);
      WRITE_TRUE_FALSE_SETTING (StartupWipeButton);
      WRITE_TRUE_FALSE_SETTING (StartupPreserveButton);
      WRITE_TRUE_FALSE_SETTING (StartupResumeButton);
      WRITE_TRUE_FALSE_SETTING (CustomResumeButton);
      WRITE_TRUE_FALSE_SETTING (DskyFullButton);
      WRITE_TRUE_FALSE_SETTING (DskyHalfButton);
      WRITE_TRUE_FALSE_SETTING (DskyLiteButton);
      WRITE_TRUE_FALSE_SETTING (AgcDebugNormalButton);
      WRITE_TRUE_FALSE_SETTING (AgcDebugMonitorButton);
      WRITE_TRUE_FALSE_SETTING (DedaFullButton);
      WRITE_TRUE_FALSE_SETTING (DedaHalfButton);
      WRITE_TRUE_FALSE_SETTING (AeaDebugNormalButton);
      WRITE_TRUE_FALSE_SETTING (AeaDebugMonitorButton);
      WRITE_TRUE_FALSE_SETTING (TelemetryResizable);
      WRITE_TRUE_FALSE_SETTING (TelemetryRetro);
      Fout.Close ();
    }
  else
    {
      wxMessageBox (wxT ("Cannot create VirtualAGC.cfg.\nConfiguration not be saved!"), wxT ("Warning"), wxOK | wxICON_HAND);
    }
}

// This function forms and outputs the file lm_simulator.ini.  Returns true
// on success, false on failure.
bool
VirtualAGC::FormLmsIni (void)
{
  bool IsLM = true;
  wxFile Fout;
  if (Fout.Create (wxT ("LM_Simulator/lm_simulator.ini"), true))
    {
      if (Luminary99Button->GetValue ())
	{
	  // These are the numbers for LM 7 --- must correct or fix.
	  Fout.Write (wxT ( "LM_Weight_Ascent_KG           4670.0\n"
			    "LM_Weight_Descent_KG          10694.0\n"
			    "Ascent_Propellant_Mass_KG     2353.0\n"
			    "Ascent_Thrust_N               15600.0\n"
			    "Ascent_Specific_Impulse_MS    3050.0\n"
			    "Descent_Propellant_Mass_KG    8355.0\n"
			    "Descent_Propulsion_Min_N      4560.0\n"
			    "Descent_Propulsion_Max_N      45040.0\n"
			    "Descent_Specific_Impulse_MS   3050.0\n"
			    "RCS_Propellant_Mass_KG        287.0\n"
			    "RCS_Thrust_N                  445.0\n"
			    "RCS_Specific_Impulse_MS       2840.0\n"
			  )
		      );
	}
      else if (Luminary131Button->GetValue ())
	{
	  // These are the numbers for LM 7 --- must correct or fix.
	  Fout.Write (wxT ( "LM_Weight_Ascent_KG           4670.0\n"
			    "LM_Weight_Descent_KG          10694.0\n"
			    "Ascent_Propellant_Mass_KG     2353.0\n"
			    "Ascent_Thrust_N               15600.0\n"
			    "Ascent_Specific_Impulse_MS    3050.0\n"
			    "Descent_Propellant_Mass_KG    8355.0\n"
			    "Descent_Propulsion_Min_N      4560.0\n"
			    "Descent_Propulsion_Max_N      45040.0\n"
			    "Descent_Specific_Impulse_MS   3050.0\n"
			    "RCS_Propellant_Mass_KG        287.0\n"
			    "RCS_Thrust_N                  445.0\n"
			    "RCS_Specific_Impulse_MS       2840.0\n"
			  )
		      );
	}
      else if (AgcCustomButton->GetValue ()) // Pretend generalized LM
	{
	  // These are the numbers for LM 7 --- must correct or fix.
	  Fout.Write (wxT ( "LM_Weight_Ascent_KG           4670.0\n"
			    "LM_Weight_Descent_KG          10694.0\n"
			    "Ascent_Propellant_Mass_KG     2353.0\n"
			    "Ascent_Thrust_N               15600.0\n"
			    "Ascent_Specific_Impulse_MS    3050.0\n"
			    "Descent_Propellant_Mass_KG    8355.0\n"
			    "Descent_Propulsion_Min_N      4560.0\n"
			    "Descent_Propulsion_Max_N      45040.0\n"
			    "Descent_Specific_Impulse_MS   3050.0\n"
			    "RCS_Propellant_Mass_KG        287.0\n"
			    "RCS_Thrust_N                  445.0\n"
			    "RCS_Specific_Impulse_MS       2840.0\n"
			  )
		      );
	}
      else // CM
	{
	  IsLM = false;
	  // These numbers are meaningless for the CM, but LM_Simulator
	  // isn't designed for the CM (though nevertheless useful) and
	  // will abort if some values aren't present.
	  Fout.Write (wxT ( "LM_Weight_Ascent_KG           4670.0\n"
			    "LM_Weight_Descent_KG          10694.0\n"
			    "Ascent_Propellant_Mass_KG     2353.0\n"
			    "Ascent_Thrust_N               15600.0\n"
			    "Ascent_Specific_Impulse_MS    3050.0\n"
			    "Descent_Propellant_Mass_KG    8355.0\n"
			    "Descent_Propulsion_Min_N      4560.0\n"
			    "Descent_Propulsion_Max_N      45040.0\n"
			    "Descent_Specific_Impulse_MS   3050.0\n"
			    "RCS_Propellant_Mass_KG        287.0\n"
			    "RCS_Thrust_N                  445.0\n"
			    "RCS_Specific_Impulse_MS       2840.0\n"
			  )
		      );
	}
#ifdef WIN32
      Fout.Write (wxT ("Operating_System Windows\n"));
#else
      Fout.Write (wxT ("Operating_System Linux\n"));
#endif 
      Fout.Write (wxT ("ServerIP         localhost\n"));
      if (IsLM)
        Fout.Write (wxT ("ServerSocket     19801\n"));
      else
        Fout.Write (wxT ("ServerSocket     19701\n"));
      if (DeviceDskyCheckbox->GetValue () && DskyLiteButton->GetValue ())
	Fout.Write (wxT ("dsky             on\n"));
      else
	Fout.Write (wxT ("dsky             off\n"));
      if (DeviceDiscoutCheckbox->GetValue ())
	Fout.Write (wxT ("output           on\n"));
      else
	Fout.Write (wxT ("output           off\n"));
      if (DeviceSysinCheckbox->GetValue ())
	Fout.Write (wxT ("system           on\n"));
      else
	Fout.Write (wxT ("system           off\n"));
      if (DeviceCrewinCheckbox->GetValue ())
	Fout.Write (wxT ("crew             on\n"));
      else
	Fout.Write (wxT ("crew             off\n"));
      if (DeviceImuCheckbox->GetValue ())
	Fout.Write (wxT ("imu              on\n"));
      else
	Fout.Write (wxT ("imu              off\n"));
      if (DevicePropulsionCheckbox->GetValue ())
	Fout.Write (wxT ("attitude         on\n"));
      else
	Fout.Write (wxT ("attitude         off\n"));
      Fout.Write (wxT ("FDAI_Update_Rate 10\n"));   
      Fout.Close ();
    }
  else
    {
      wxMessageBox (wxT ("Cannot create lm_simulator.ini.\nLM-Simulator won\'t run properly."), wxT ("Warning"), wxOK | wxICON_HAND);
      return (false);
    }
  return (true);
}

// Forms command lines for other programs we want to execute for the
// simulation.  Returns true on success, false on failure.
bool
VirtualAGC::FormCommands (void)
{
  CmSim = LmSim = AeaSim = false;
  
#ifdef __APPLE__
    wxString ExecutableDirectory = wxT ("../MacOS");
#else
    wxString ExecutableDirectory = wxT ("..") + PathDelimiter + wxT ("bin");
#endif
    wxString CoreBin, CMorLM, Port, TelemetrySwitches;
    
    if (DeviceAgcCheckbox->GetValue ())
      {
        yaAGC = ExecutableDirectory + PathDelimiter + wxT ("yaAGC");
	if (AgcDebugMonitorButton->GetValue ())
	  yaAGC += wxT (" --debug");
      }
    else
      yaAGC = wxT ("");
    if (DeviceDskyCheckbox->GetValue ())
      {
        yaDSKY = ExecutableDirectory + PathDelimiter;	
#ifdef YADSKY2
#ifdef __APPLE__
	yaDSKY += wxT ("yaDSKY2.app/Contents/MacOS/");
#endif
	yaDSKY += wxT ("yaDSKY2");
#else      
#ifdef __APPLE__
	yaDSKY += wxT ("yaDSKY.app/Contents/MacOS/");
#endif
	yaDSKY += wxT ("yaDSKY --relative-pixmaps");
#endif
	//if (DeviceTelemetryCheckbox->GetValue ())
	//  yaDSKY += wxT (" --test-downlink");
	if (DskyHalfButton->GetValue ())
	  yaDSKY += wxT (" --half-size");
      }
    else
      yaDSKY = wxT ("");
    if (DeviceAcaCheckbox->GetValue ())
      {
        // By default we want to use yaACA3 here.  However, if someone
	// has gone to the trouble to configure yaACA --- in which case
	// yaACA-0.cfg will exist --- we use it instead.
	if (wxFileExists (wxT ("yaACA-0.cfg")))
	  yaACA = ExecutableDirectory + PathDelimiter + wxT ("yaACA");
	else
          yaACA = ExecutableDirectory + PathDelimiter + wxT ("yaACA3");
      }
    else
      yaACA = wxT ("");
    if (DeviceTelemetryCheckbox->GetValue ())
      {
        yaTelemetry = ExecutableDirectory + PathDelimiter;
#ifdef __APPLE__
	yaTelemetry += wxT ("yaTelemetry.app/Contents/MacOS/");
#endif
	yaTelemetry += wxT ("yaTelemetry");
	if (TelemetryResizable->GetValue ())
	  yaTelemetry += wxT (" --simple");
      }
    else
      yaTelemetry = wxT ("");
    if (DeviceAeaCheckbox->GetValue ())
      {
        AeaSim = true;
        yaAGS = ExecutableDirectory + PathDelimiter + wxT ("yaAGS");
	if (AeaDebugMonitorButton->GetValue ())
	  yaAGS += wxT (" --debug");
	if (FlightProgram4Button->GetValue ())
	  CoreBin = wxT ("source/FP4/FP4.bin");
	else if (FlightProgram5Button->GetValue ())
	  CoreBin = wxT ("source/FP5/FP5.bin");
	else if (FlightProgram6Button->GetValue ())
	  CoreBin = wxT ("source/FP6/FP6.bin");
	else if (FlightProgram7Button->GetValue ())
	  CoreBin = wxT ("source/FP7/FP7.bin");
	else if (FlightProgram8Button->GetValue ())
	  CoreBin = wxT ("source/FP8/FP8.bin");
	else if (AeaCustomButton->GetValue ())
	  CoreBin = AeaCustomFilename->GetValue ();
	else // This can't happen.
	  return (false);
	yaAGS += wxT (" --core=\"") + CoreBin + wxT ("\"");
      }
    else
      yaAGS = wxT ("");
    if (!yaAGS.IsSameAs (wxT ("")) && AeaDebugMonitorButton->GetValue ())
      {
	wxString Symtab = CoreBin + wxT (".symtab");
	if (wxFileExists (Symtab))
	  yaAGS += wxT (" --symtab=\"") + Symtab + wxT ("\"");
      }
    if (DeviceDedaCheckbox->GetValue ())
      {
        yaDEDA = ExecutableDirectory + PathDelimiter;
#ifdef YADEDA2
#ifdef __APPLE__
	yaDEDA += wxT ("yaDEDA2.app/Contents/MacOS/");
#endif
        yaDEDA += wxT ("yaDEDA2");
#else      
#ifdef __APPLE__
	yaDEDA += wxT ("yaDEDA.app/Contents/MacOS/");
#endif
        yaDEDA += wxT ("yaDEDA --relative-pixmaps");
#endif
	if (DedaHalfButton->GetValue ())
	  yaDEDA += wxT (" --half-size");
      }
    else
      yaDEDA = wxT ("");
    if (DeviceCpumonCheckbox->GetValue ())
      LM_Simulator = wxT ("wish VirtualAGC.tcl --cfg=lm_simulator.ini");
    else
      LM_Simulator = wxT ("");
    if (Colossus249Button->GetValue ())
      {
        CoreBin = wxT ("source/Colossus249/Colossus249.bin");
	CMorLM = wxT ("CM");
	Port = wxT ("19697");
      }
    else if (Comanche55Button->GetValue ())
      {
        CoreBin = wxT ("source/Comanche055/Comanche055.bin");
	CMorLM = wxT ("CM");
	Port = wxT ("19697");
      }
    else if (Luminary99Button->GetValue ())
      {
        CoreBin = wxT ("source/Luminary099/Luminary099.bin");
	CMorLM = wxT ("LM");
	Port = wxT ("19797");
      }
    else if (Luminary131Button->GetValue ())
      {
        CoreBin = wxT ("source/Luminary131/Luminary131.bin");
	CMorLM = wxT ("LM");
	Port = wxT ("19797");
      }
    else if (Artemis72Button->GetValue ())
      {
        CoreBin = wxT ("source/Artemis072/Artemis072.bin");
	CMorLM = wxT ("CM");
	Port = wxT ("19697");
      }
    else if (ValidationButton->GetValue ())
      {
        CoreBin = wxT ("source/Validation/Validation.bin");
	CMorLM = wxT ("CM");
	Port = wxT ("19697");
      }
    else if (AgcCustomButton->GetValue ())
      {
        CoreBin = AgcCustomFilename->GetValue ();
	CMorLM = wxT ("LM");
	Port = wxT ("19797");
      }
    else // This can't happen
      return (false);
    if (CMorLM.IsSameAs (wxT ("CM")))
      {
        CmSim = true;
        TelemetrySwitches = wxT (" --port=19700 --spacecraft=CM");
      }
    else 
      {
        LmSim = true;
        TelemetrySwitches = wxT (" --port=19800 --spacecraft=LM");
      }
    if (!yaTelemetry.IsSameAs (wxT ("")))
      yaTelemetry += TelemetrySwitches;
    if (!yaAGC.IsSameAs (wxT ("")))
      {
	yaAGC += wxT (" --core=\"") + CoreBin + wxT ("\" --port=") + Port + wxT (" --cfg=") + CMorLM + wxT (".ini");
	if (StartupResumeButton->GetValue () && wxFileExists (CMorLM + wxT (".core")))
	  yaAGC += wxT (" --resume=") + CMorLM + wxT (".core");
	if (CustomResumeButton->GetValue () && wxFileExists (CoreFilename->GetValue ()))
	  yaAGC += wxT (" --resume=\"") + CoreFilename->GetValue () + wxT ("\"");
	if (AgcDebugMonitorButton->GetValue ())
	  {
	    wxString Symtab = CoreBin + wxT (".symtab");
	    if (wxFileExists (Symtab))
	      yaAGC += wxT (" --symtab=\"") + Symtab + wxT ("\"");
	  }
      }
    if (!yaDSKY.IsSameAs (wxT ("")))
      yaDSKY += wxT (" --cfg=") + CMorLM + wxT (".ini --port=") + Port;
    return (true);
}

// This function takes the various command-lines which have already
// been created as wxStrings and creates shell scripts or batch files
// based on them

#if defined (WIN32)

bool
VirtualAGC::FormScript (void)
{
  wxFile Fout;
  if (Fout.Create (wxT ("simulate.bat"), true))
    {
      if (!yaAGC.IsSameAs (wxT ("")))
        {
	  if (AgcDebugMonitorButton->GetValue ())
	    Fout.Write (wxT ("cmd /C start /WAIT "));
          Fout.Write (yaAGC + wxT (EOL));
	}
      if (!yaAGS.IsSameAs (wxT ("")))
        {
	  if (AeaDebugMonitorButton->GetValue ())
	    Fout.Write (wxT ("cmd /C start /WAIT "));
          Fout.Write (yaAGS + wxT (EOL));
	}
      if (!yaDEDA.IsSameAs (wxT ("")))
        Fout.Write (yaDEDA + wxT (EOL));
      if (!yaDSKY.IsSameAs (wxT ("")))
        Fout.Write (yaDSKY + wxT (EOL));
      if (!yaACA.IsSameAs (wxT ("")))
        Fout.Write (yaACA + wxT (EOL));
      if (!yaTelemetry.IsSameAs (wxT ("")))
        Fout.Write (yaTelemetry + wxT (EOL));
      if (!LM_Simulator.IsSameAs (wxT ("")))
        Fout.Write (LM_Simulator + wxT (EOL));
      Fout.Close ();
    }
  else
    {
      wxMessageBox (wxT ("Cannot create simulation script, simulate.bat."), wxT ("Warning"), wxOK | wxICON_HAND);
      return (false);
    }
  if (Fout.Create (wxT ("simulate2.bat"), true))
    {
      if (StartupWipeButton->GetValue ())
        {
	  Fout.Write (wxT ("del LM.core" EOL));
	  Fout.Write (wxT ("del CM.core" EOL));
	}
      Fout.Write (wxT ("..\\bin\\WinAGC.exe <simulate.bat" EOL));
      Fout.Close ();
    }
  else
    {
      wxMessageBox (wxT ("Cannot create shutdown manager, simulate.bat."), wxT ("Warning"), wxOK | wxICON_HAND);
      return (false);
    }
  return (true);
}

#else // Presumably Linux or Mac OS X

bool
VirtualAGC::FormScript (void)
{
#ifdef __APPLE__
    wxString ExecutableDirectory = wxT ("../MacOS");
#else
    wxString ExecutableDirectory = wxT ("..") + PathDelimiter + wxT ("bin");
#endif
  wxFile Fout;
  if (Fout.Create (wxT ("simulate"), true, wxS_DEFAULT | wxS_IXUSR | wxS_IXGRP))
    {
      Fout.Write (wxT ("#!/bin/bash\n"));
#ifdef __APPLE__
      Fout.Write (wxT ("PATH=$PATH:/usr/X11/bin\n"));
#endif      
      Fout.Write (wxT ("PIDS=\n"));
      if (StartupWipeButton->GetValue ())
        {
	  Fout.Write (wxT ("rm LM.core\n"));
	  Fout.Write (wxT ("rm CM.core\n"));
	}
      
      // Run DSKY
      if (DeviceDskyCheckbox->GetValue ())
        {
	  if (!DskyLiteButton->GetValue ())
	    {
	      //if (DeviceTelemetryCheckbox->GetValue ())
	      // Fout.Write (wxT ("xterm -geometry 80x43 -e "));
	      Fout.Write (yaDSKY + wxT (" &\n"));
	      Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	    }
	}
      
      // Run DEDA
      if (DeviceDedaCheckbox->GetValue ())
        {
	  Fout.Write (yaDEDA + wxT (" &\n"));
	  Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	}
      
      // Run AEA
      if (DeviceAeaCheckbox->GetValue ())
        {
	  if (AeaDebugMonitorButton->GetValue ())
	    Fout.Write (wxT ("xterm -sb -geometry 112x40 -e "));
	  Fout.Write (yaAGS + wxT (" &\n"));
	  Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	}
      
      // Run ACA
      if (DeviceAcaCheckbox->GetValue ())
        {
	  Fout.Write (yaACA + wxT (" &\n"));
	  Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	}
      
      // Run AGC
      if (DeviceAgcCheckbox->GetValue ())
        {
	  if (AgcDebugMonitorButton->GetValue ())
	    Fout.Write (wxT ("xterm -sb -geometry 112x40 -e "));
	  Fout.Write (yaAGC + wxT (" &\n"));
	  Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	}
	
      // Run LM-Simulator
      if (DeviceCpumonCheckbox->GetValue ())
        {
	  // The one-second delay here is because I've noted intermittent
	  // instances in which LM_Simulator fails to connect.  I believe
	  // this may be because it tries to connect before yaAGC is
	  // running (perhaps because of the time it takes to load symbol
	  // tables or something).
	  Fout.Write (LM_Simulator + wxT (" &\n"));
	  Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	}
	
      // Run yaTelemetry
      if (DeviceTelemetryCheckbox->GetValue ())
        {
	  Fout.Write (yaTelemetry + wxT (" &\n"));
	  Fout.Write (wxT ("PIDS=\"$! ${PIDS}\"\n"));
	}
	
      Fout.Write (wxT ("export PIDS\n"));
      Fout.Write (ExecutableDirectory + wxT ("/SimStop\n"));
#ifdef __APPLE__	  
	  // In Mac OS X, starting LM_Simulator starts a child process which
	  // actually runs the program, and when SimStop eventually kills the
	  // parent it won't kill the child process.  So here's a little bit
	  // of stuff that accomplishes that.  It actually kills all child
	  // processes of the current shell, which includes a lot of 
	  // processes that SimStop killed off already.
	  Fout.Write (wxT ("kill `ps -o pid -g $$ | tail -n +2`\n"));
#endif
      Fout.Close ();
    }
  else
    {
      wxMessageBox (wxT ("Cannot create simulation script."), wxT ("Warning"), wxOK | wxICON_HAND);
      return (false);
    }
  return (true);
}

#endif





Simulation::Simulation(wxWindow* parent, int id, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
    wxFrame(parent, id, title, pos, size, wxCAPTION|wxMINIMIZE_BOX|wxSTAY_ON_TOP|wxSYSTEM_MENU)
{
    // begin wxGlade: Simulation::Simulation
    DetailPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL);
    ScriptPanel = new wxPanel(DetailPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL);
    UplinkPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL);
    sizer_32_staticbox = new wxStaticBox(ScriptPanel, -1, wxT("To do the same thing from a command line ..."));
    sizer_33_staticbox = new wxStaticBox(UplinkPanel, -1, wxT("Digital uplink status"));
    PatchBitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxT("ApolloPatch2.png"), wxBITMAP_TYPE_ANY));
    SimulationLabel = new wxStaticText(this, ID_SIMULATIONLABEL, wxT("Apollo 13 Lunar Module\nsimulation in progress!"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
    MoreButton = new wxButton(this, ID_MORE, wxT("More"));
    LessButton = new wxButton(this, ID_LESS, wxT("Less"));
    UploadButton = new wxButton(this, ID_UPLOAD, wxT("Uplink"));
    UplinkText = new wxTextCtrl(UplinkPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL|wxTE_RICH);
    ScriptText = new wxTextCtrl(ScriptPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL|wxTE_RICH);

    set_properties();
    do_layout();
    // end wxGlade
    
    Timer = new TimerClass;
}


BEGIN_EVENT_TABLE(Simulation, wxFrame)
    // begin wxGlade: Simulation::event_table
    EVT_BUTTON(ID_MORE, Simulation::MoreEvent)
    EVT_BUTTON(ID_LESS, Simulation::LessEvent)
    EVT_BUTTON(ID_UPLOAD, Simulation::UploadEvent)
    // end wxGlade
END_EVENT_TABLE();


// wxGlade: add Simulation event handlers


void Simulation::MoreEvent(wxCommandEvent &event)
{
  Show (false);
  LessButton->Enable ();
  MoreButton->Disable ();
  DetailPanel->Show ();
  InvalidateBestSize ();
  Layout ();
  Fit ();
  Show (true);
}


void Simulation::LessEvent(wxCommandEvent &event)
{
  Show (false);
  LessButton->Disable ();
  MoreButton->Enable ();
  DetailPanel->Hide ();
  InvalidateBestSize ();
  Layout ();
  Fit ();
  Show (true);
}


void Simulation::UploadEvent(wxCommandEvent &event)
{
    if (Timer->IsRunning ())
      {
        Timer->Stop ();
	for (; OnShellout < NumShellouts; OnShellout++)
	  free (UplinkShellouts[OnShellout]);
	OnShellout = NumShellouts = 0;
	UploadButton->SetLabel (wxT ("Uplink"));
	UploadButton->SetToolTip(wxT("Click this button to use the digital-uplink to send data to the AGC or AEA from a pre-created script of commands.  This allows setting the AGC or AEA to a known configuration suitable for your purposes, much in the same way mission control could have done this in real missions."));
	MoreButton->Enable (MoreEnabled);
	LessButton->Enable (LessEnabled);
	UplinkPanel->Hide ();
	DetailPanel->Show (DetailShown);
	Hide ();
	InvalidateBestSize ();
	Layout ();
	Fit ();
	Refresh ();
	Update ();
	Show ();
	return;
      }
    wxString Dummy;
    Dummy = MainFrame->ResourceDirectory;
    Dummy += PATH_DELIMITER;
    Dummy += wxT ("scenarios");
    wxFileDialog *Dialog = new wxFileDialog (this, wxT ("Choose script for digital upload to AGC or AEA"),
    					     Dummy,  wxT (""), wxT ("Script files (*.txt)|*.txt"),
					     wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR);  
    if (wxID_OK == Dialog->ShowModal ())
      {
	wxString Pathname = Dialog->GetPath ();  
	Upload (Pathname);
      }
Done:      
    delete Dialog;
    wxSetWorkingDirectory (MainFrame->ResourceDirectory);
}


void Simulation::set_properties()
{
    // begin wxGlade: Simulation::set_properties
    SetTitle(wxT("Simulation status"));
    wxIcon _icon;
    _icon.CopyFromBitmap(wxBitmap(wxT("ApolloPatch2.png"), wxBITMAP_TYPE_ANY));
    SetIcon(_icon);
    SetBackgroundColour(wxColour(255, 255, 255));
    SimulationLabel->SetFont(wxFont(14, wxDEFAULT, wxNORMAL, wxBOLD, 0, wxT("")));
    MoreButton->SetToolTip(wxT("Click this button to display the script which is being run.  This could be helpful to know if you'd like to run a custom simulation that VirtualAGC can't handle, such as having 2 DSKYs, ganging multiple PCs interconnected via ethernet, etc."));
    LessButton->SetToolTip(wxT("Click this button to hide the script data."));
    LessButton->Enable(false);
    UploadButton->SetToolTip(wxT("Click this button to use the digital-uplink to send data to the AGC or AEA from a pre-created script of commands.  This allows setting the AGC or AEA to a known configuration suitable for your purposes, much in the same way mission control could have done this in real missions."));
    UplinkText->SetMinSize(wxSize(480, 480));
    UplinkText->SetBackgroundColour(wxColour(230, 230, 230));
    UplinkText->SetFont(wxFont(10, wxMODERN, wxNORMAL, wxNORMAL, 0, wxT("")));
    UplinkPanel->SetBackgroundColour(wxColour(255, 255, 255));
    UplinkPanel->Hide();
    ScriptText->SetMinSize(wxSize(480, 480));
    ScriptText->SetBackgroundColour(wxColour(230, 230, 230));
    ScriptText->SetFont(wxFont(8, wxMODERN, wxNORMAL, wxNORMAL, 0, wxT("")));
    DetailPanel->SetBackgroundColour(wxColour(255, 255, 255));
    // end wxGlade
}


void Simulation::do_layout()
{
    // begin wxGlade: Simulation::do_layout
    wxBoxSizer* sizer_25 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* sizer_17 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_31 = new wxBoxSizer(wxVERTICAL);
    wxStaticBoxSizer* sizer_32 = new wxStaticBoxSizer(sizer_32_staticbox, wxHORIZONTAL);
    wxStaticBoxSizer* sizer_33 = new wxStaticBoxSizer(sizer_33_staticbox, wxHORIZONTAL);
    wxBoxSizer* sizer_16 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_27 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* sizer_26 = new wxBoxSizer(wxHORIZONTAL);
    sizer_25->Add(20, 10, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_26->Add(20, 20, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_26->Add(PatchBitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_26->Add(20, 20, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_25->Add(sizer_26, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_25->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_27->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_27->Add(SimulationLabel, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_27->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_25->Add(sizer_27, 0, wxEXPAND, 0);
    sizer_25->Add(20, 20, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_16->Add(20, 20, 1, 0, 0);
    sizer_16->Add(MoreButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_16->Add(50, 20, 0, 0, 0);
    sizer_16->Add(LessButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    sizer_16->Add(50, 20, 0, 0, 0);
    sizer_16->Add(UploadButton, 0, 0, 0);
    sizer_16->Add(20, 20, 1, 0, 0);
    sizer_25->Add(sizer_16, 0, wxEXPAND, 0);
    sizer_25->Add(20, 10, 0, 0, 0);
    sizer_33->Add(UplinkText, 1, wxEXPAND, 0);
    UplinkPanel->SetSizer(sizer_33);
    sizer_25->Add(UplinkPanel, 1, wxEXPAND, 0);
    sizer_17->Add(10, 20, 0, 0, 0);
    sizer_32->Add(ScriptText, 1, wxEXPAND, 0);
    ScriptPanel->SetSizer(sizer_32);
    sizer_31->Add(ScriptPanel, 0, wxEXPAND, 0);
    sizer_31->Add(20, 10, 0, 0, 0);
    sizer_17->Add(sizer_31, 1, wxEXPAND, 0);
    sizer_17->Add(10, 20, 0, 0, 0);
    DetailPanel->SetSizer(sizer_17);
    sizer_25->Add(DetailPanel, 1, wxEXPAND, 0);
    SetSizer(sizer_25);
    sizer_25->Fit(this);
    Layout();
    // end wxGlade
}

void 
Simulation::WriteSimulationLabel (wxString Label)
{
  SimulationLabel->SetLabel (Label + wxT ("\nAGC simulation running!"));
  SimulationLabel->Fit ();
  Layout ();
}


void
Simulation::Upload (wxString &Filename)
{
  wxTextFile File;
  UnitType = UT_UNKNOWN;
  if (File.Open (Filename))
    {
      // Format of the file:  The type of the file (CM, LM, or AEA) is determined by the first
      // character of the file, which is C, L, or A.  In the remainder of the file:
      //	1. All characters between a '#' and an end-of-line are ignored.
      //	2. All characters between an '!' and the end-of-line are treated as a shell
      //	   command.  An example of how to use something like this would be if you
      //	   were making a tutorial on using the AGC, or a museum display, and wished
      //           to display something or play an audio clip at various points in the uplink.
      //	   What you can do is limited only by the software available on the computer
      //	   running the simulation.
      //	3. The following characters are translated in an obvious way to keystrokes:
      //	   a. For LM or CM AGC:
      //		VNECPKR+-0123456789
      //	        Z (which doesn't correspond to anything on the DSKY keypad) is the
      //		uplink-error-clear code.
      //	   b. For AEA:
      //		CREH+-0123456789
      //	4. A space (' ') is interpreted as an extra 0.5-second delay.
      //	5. All other characters are ignored.
      // Note that on transmission to the simulated CPU, a delay of 0.2 seconds is automatically
      // inserted after each keycode.  Z,Y,X can be used to insert extra delay.
      int i, j, Len, LineCount = File.GetLineCount (), Keycode;
      wxString Line;
      wxChar c;
      OnShellout = NumShellouts = 0;
      NumKeycodes = 0;
      for (i = 0; i < LineCount; i++)
        {
	  Line = File.GetLine (i);
	  //Line = Line.MakeUpper ();
	  Len = Line.Len ();
	  if (i == 0 && Len == 0)
	    {
	      wxMessageBox (wxT ("Ill-formed script"), wxT ("Error"), wxICON_ERROR);
	      goto Done;
	    }
	  for (j = 0; j < Len; j++)
	    {
	      c = Line.GetChar (j);
	      if (i == 0 && j == 0)
	        {
		  if (toupper (c) == 'C')
		    {
		      UnitType = UT_CM;
		      if (!MainFrame->CmSim)
		        {
			  wxMessageBox (wxT ("There is no CM simulation running"), wxT ("Error"), wxICON_ERROR);
			  goto Done;
			}
		    }
		  else if (toupper (c) == 'L')
		    {
		      UnitType = UT_LM;
		      if (!MainFrame->LmSim)
		        {
			  wxMessageBox (wxT ("There is no LM simulation running"), wxT ("Error"), wxICON_ERROR);
			  goto Done;
			}
		    }
		  else if (toupper (c) == 'A')
		    {
		      UnitType = UT_AEA;
		      if (!MainFrame->AeaSim)
		        {
			  wxMessageBox (wxT ("There is no AEA simulation running"), wxT ("Error"), wxICON_ERROR);
			  goto Done;
			}
		    }
		  else
		    {
		      wxMessageBox (wxT ("Ill-formed script"), wxT ("Error"), wxICON_ERROR);
		      goto Done;
		    }
		}
	      else if (c == '#') // Comment.
	        break;
	      else if (UnitType == UT_AEA)
	        {
		  // Not sure what to do with this stuff yet.  Ignore for now.
		  File.Close ();
		  wxMessageBox (wxT ("AEA uploads not implemented yet"), wxT ("Error"), wxICON_ERROR);
		  goto Done;
		}
	      else // UnitType == UT_CM || UnitType == UT_LM
	        {
		  switch (toupper (c))
		    {
		    case 'Z':  Keycode = 254; break;
		    case '!':  
		      if (NumShellouts < MAX_SHELLOUTS)
			{
			  char *s;
			  UplinkShellouts[NumShellouts] = (char *) malloc (Len - j);
			  for (j++, s = UplinkShellouts[NumShellouts]; j < Len; j++)
			    *s++ = Line.GetChar (j); 
			  *s = 0;
			  NumShellouts++;
			  Keycode = 253;
			}
		      else
			Keycode = -1;
		      break;
		    case 'V':  Keycode = 17; break;
		    case 'N':  Keycode = 31; break;
		    case '+':  Keycode = 26; break;
		    case '-':  Keycode = 27; break;
		    case '0':  Keycode = 16; break;
		    case '7':  Keycode = 7; break;
		    case '4':  Keycode = 4; break;
		    case '1':  Keycode = 1; break;
		    case '8':  Keycode = 8; break;
		    case '5':  Keycode = 5; break;
		    case '3':  Keycode = 3; break;
		    case '2':  Keycode = 2; break;
		    case '9':  Keycode = 9; break;
		    case '6':  Keycode = 6; break;
		    case 'C':  Keycode = 30; break;
		    case 'K':  Keycode = 25; break;
		    case 'E':  Keycode = 28; break;
		    case 'R':  Keycode = 18; break;
		    case ' ':  Keycode = 255; break;
		    case 'P':  // The "PRO" key has no keycode, and falls through.
		    default:   Keycode = -1; break;
		    }
		  if (Keycode >= 0)
		    {
		      if (NumKeycodes < sizeof (Keycodes))
		        Keycodes[NumKeycodes++] = Keycode;
		    }
		}
	    }
	}
      File.Close ();
      if (NumKeycodes == sizeof (Keycodes))
        {
	  wxMessageBox (wxT ("Too much data in script"), wxT ("Error"), wxICON_ERROR);
	  goto Done;
	}
      // The Keycodes[] array, consisting of NumKeycodes bytes, can now be transmitted to
      // the simulated CPU.  All we really need to worry about, though, is getting the
      // background timer started that's going to handle it.
      if (UnitType == UT_AEA)
        Timer->Portnum = 19906;
      else if (UnitType == UT_LM)
        Timer->Portnum = 19806;
      else // UnitType == UT_CM
        Timer->Portnum = 19706;
      MoreEnabled = MoreButton->IsEnabled ();
      MoreButton->Disable ();
      LessEnabled = LessButton->IsEnabled ();
      LessButton->Disable ();
      DetailShown = DetailPanel->IsShown ();
      DetailPanel->Hide ();
      UplinkPanel->Show (true);
      UplinkText->Clear ();
      if (UnitType == UT_AEA)
	UplinkText->AppendText (wxT ("Digital uplink to AEA starting ..."));
      else if (UnitType == UT_CM)
	UplinkText->AppendText (wxT ("Digital uplink to CM starting ..."));
      else if (UnitType == UT_LM)
	UplinkText->AppendText (wxT ("Digital uplink to LM starting ..."));
      UploadButton->SetLabel (wxT ("Cancel"));
      UploadButton->SetToolTip (wxT ("Click this button to halt the digital-uplink in progress.  Only the uplink and not the simulation itself will terminate."));
      Hide ();
      InvalidateBestSize ();
      Layout ();
      Fit ();
      Refresh ();
      Update ();
      Show ();
      Timer->KeycodeIndex = 0;
      Timer->Start (100);
    }
  else
    wxMessageBox (wxT ("Could not open file"), wxT ("Error"), wxICON_ERROR);
Done: ;
}


// This is the event handler for the background timer.  The background timer
// executes about every 100 ms. and services the socket interface.  Upon 
// receiving downlink data, it updates the output screen.

void 
TimerClass::Notify ()
{
  static int ServerSocket = -1;
  static unsigned char Packet[4];
  static int PacketSize = 0;
  static int Delaying = 0;
  static char hostname[] = "localhost";
  int i;
  unsigned char c;
  // Try to connect to the server (yaAGC) if not already connected.
  if (ServerSocket == -1)
    {
      ServerSocket = CallSocket (hostname, Portnum);
      if (ServerSocket != -1)
        {
          printf ("Digital uplink is connected.\n");
	  MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nConnected to simulated CPU."));
	}
    }
  if (ServerSocket != -1)
    {
      // Service incoming data.
      for (;;)
        {
	  i = recv (ServerSocket, (char *) &c, 1, MSG_NOSIGNAL);
	  if (i == -1)
	    {
	      // The conditions i==-1,errno==0 or 9 occur only on Win32,
	      // and I'm not sure exactly what they corresponds to---but
	      // empirically I find that ignoring them makes no difference
	      // to the operation of the program.
	      if (errno == EAGAIN || errno == 0 || errno == 9)
	        i = 0;
	      else
	        {	
		  //wxString Dummy;
		  //Dummy << wxT ("yaTelemetry reports server error ") << errno;
		  //wxMessageBox (Dummy);
		  printf ("Digital uplink reports server error %d\n", errno);
	          MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nConnection failure."));
		  close (ServerSocket);
		  ServerSocket = -1;
		  break;
	        }
	    }
	  if (i == 0)
	    break;
	  if (0 == (0xc0 & c))
	    PacketSize = 0;
	  if (PacketSize != 0 || (0xc0 & c) == 0)	      
	    { 
	      Packet[PacketSize++] = c;
	      if (PacketSize >= 4)
		{
		  PacketSize = 0;   
		  // If I wanted to do something with incoming data, I'd do it here!
		  
		}  
	    }
	}
      // Handle outgoing data. This function is called every 100 ms.  Delaying holds
      // a count for the delay between outputting packets.
      if (Delaying > 0)
        Delaying--;
      else if (KeycodeIndex < MainFrame->SimulationWindow->NumKeycodes)
        {
	  static int LastKeycode = -2;
	  int Keycode = MainFrame->SimulationWindow->Keycodes[KeycodeIndex++];
	  if (Keycode == 255)
	    {
	      Delaying = 5;
	      if (LastKeycode != Keycode)
	        MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\n."));
	      else 
	        MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" ."));
	    }
	  else
	    {
	      switch (Keycode)
	        {
		case 253: // Shellout.
		  if (OnShellout < NumShellouts)
		    {
		      //printf ("Shellout: %s\n", UplinkShellouts[OnShellout]);
		      wxExecute (wxString::FromAscii (UplinkShellouts[OnShellout]));
		      free (UplinkShellouts[OnShellout]);
		      OnShellout++;
		    }
		  Keycode = -1;
		  break;
		case 254: MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nATTN")); break;
		case 16:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 0")); break;
		case 1:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 1")); break;
		case 2:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 2")); break;
		case 3:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 3")); break;
		case 4:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 4")); break;
		case 5:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 5")); break;
		case 6:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 6")); break;
		case 7:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 7")); break;
		case 8:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 8")); break;
		case 9:   MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" 9")); break;
		case 17:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nVERB")); break;
		case 31:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" NOUN")); break;
		case 26:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" +")); break;
		case 27:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" -")); break;
		case 30:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nCLR")); break;
		case 25:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nKEY-REL")); break;
		case 28:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT (" ENTR")); break;
		case 18:  MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nRST")); break;
		default:  Keycode = -1; break;
		}	   
	      if (Keycode != -1)
	        {   
		  if (Keycode == 254)
		    Keycode = 0;
		  else
		    {
		      Keycode &= 037;
		      Keycode |= ((Keycode << 10) | ((Keycode ^ 037) << 5));
		    }
		  FormIoPacket (0173, Keycode, Packet);
		  i = send (ServerSocket, (const char *) Packet, 4, MSG_NOSIGNAL);
		  if (i == SOCKET_ERROR && SOCKET_BROKEN)
		    {
		      close (ServerSocket);
		      ServerSocket = -1;
		      MainFrame->SimulationWindow->UplinkText->AppendText (wxT ("\nUplink failure."));
		      wxMessageBox (wxT ("Server error on digital uplink"), wxT ("Error"), wxICON_ERROR);
		      goto Error;
		    }
		  Delaying = 2;
	        }
	    }
	  LastKeycode = Keycode;
	}
      else // All done!
        {
	Error:
	  MainFrame->SimulationWindow->UploadButton->SetLabel (wxT ("Uplink"));
	  MainFrame->SimulationWindow->UploadButton->SetToolTip(wxT("Click this button to use the digital-uplink to send data to the AGC or AEA from a pre-created script of commands.  This allows setting the AGC or AEA to a known configuration suitable for your purposes, much in the same way mission control could have done this in real missions."));
	  MainFrame->SimulationWindow->MoreButton->Enable (MainFrame->SimulationWindow->MoreEnabled);
	  MainFrame->SimulationWindow->LessButton->Enable (MainFrame->SimulationWindow->LessEnabled);
	  MainFrame->SimulationWindow->UplinkPanel->Hide ();
	  MainFrame->SimulationWindow->DetailPanel->Show (MainFrame->SimulationWindow->DetailShown);
	  MainFrame->SimulationWindow->Hide ();
	  MainFrame->SimulationWindow->InvalidateBestSize ();
	  MainFrame->SimulationWindow->Layout ();
	  MainFrame->SimulationWindow->Fit ();
	  MainFrame->SimulationWindow->Refresh ();
	  MainFrame->SimulationWindow->Update ();
	  MainFrame->SimulationWindow->Show ();
	  Stop ();
	}
    }
}



































