/*
		CaPriCe Forever - Amstrad CPC 464/664/6128 emulator
		Copyright (C) 2014-2016 by Frédéric Coste

		This program is free software: you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation, either version 3 of the License, or
		(at your option) any later version.

		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.

		You should have received a copy of the GNU General Public License
		along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#include <vcl.h>
#include <FileCtrl.hpp>
#include <tchar.h>
#pragma hdrstop
#include "TEmulator.h"
#include "TFormEmulatorSettings.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"


#define SETTINGS_FILTER             "CaPriCe Settings (.ini)|*.ini|"\
																		"All files|*.*"
#define XMASS_FILTER								"X-Mass storage (*.xmass)|*.xmass|"\
																		"All files|*.*"
#define XMEM_FILTER								  "X-Mem storage (*.xmem)|*.xmem|"\
																		"binary files (*.bin)|*.bin|"\
																		"All files|*.*"
#define ROM_FILTER								  "ROM files (*.rom)|*.rom|"\
																		"binary files (*.bin)|*.bin|"\
																		"All files|*.*"

#define SETTINGS_INI_EXT            ".ini"
#define XMASS_EXT                   ".xmass"
#define XMEM_EXT                    ".xmem"
#define ROM_EXT                     ".rom"


//=================================
// Options

//
//=================================


typedef struct
{
  const char* Name;
  tUChar CPCModel;
} tDeviceInfo;


#define NB_DEVICES    8
static const tDeviceInfo Devices[NB_DEVICES]=
{
  { "CPC 464 UK", CPC_MODEL_464_UK },
	{ "CPC 464 FR", CPC_MODEL_464_FR },
  { "CPC 464 SP", CPC_MODEL_464_SP },
  { "CPC 664 UK FDD", CPC_MODEL_664_UK },
  { "CPC 664 UK LDD", CPC_MODEL_664_FR },
  { "CPC 6128 UK", CPC_MODEL_6128_UK },
  { "CPC 6128 FR", CPC_MODEL_6128_FR },
  { "CPC 6128 SP", CPC_MODEL_6128_SP }
};


TFormEmulatorSettings *FormEmulatorSettings;
//---------------------------------------------------------------------------
__fastcall TFormEmulatorSettings::TFormEmulatorSettings(TComponent* Owner)
  : TForm(Owner)
{
	mSettingsP = NULL;
	mUpperROMFilenames = NULL;

#ifndef USE_SILICON_DISC
	CheckBoxUse256kSiliconDisc->Visible = false;
#endif /* USE_SILICON_DISC */

#ifndef USE_RAM_4MB
	CheckBoxUse4MMemoryExtension->Visible = false;
#endif /* USE_RAM_4MB */

#ifndef ENABLE_TMPI_SPEECH
  CheckBoxUseTechniMusique->Visible = false;
#endif /* ENABLE_TMPI_SPEECH */

#ifndef ENABLE_PLAYCITY
  CheckBoxUsePlayCity->Visible = false;
#endif /* ENABLE_PLAYCITY */

#ifndef ENABLE_DIGIBLASTER
  CheckBoxUseDigiblaster->Visible = false;
#endif /* ENABLE_DIGIBLASTER */

#ifndef ENABLE_MULTIFACE2
  CheckBoxUseMultiface2->Visible = false;
#endif /* ENABLE_MULTIFACE2 */

#ifndef USE_XMEM
	CheckBoxUseXMEM->Visible = false;
	CheckBoxBootXMEM->Visible = false;
	TabSheetXMEM->TabVisible = false;
#endif /* !USE_XMEM */
#ifndef USE_XMASS
	CheckBoxUseXMASS->Visible = false;
	CheckBoxXMASS512M->Visible = false;
	TabSheetXMASS->TabVisible = false;
#endif /* USE_XMASS */

  // Populate devices
  ComboBoxDevices->Items->Clear();
  for (int Index=0; Index < NB_DEVICES; Index++)
  {
    ComboBoxDevices->Items->Add(Devices[Index].Name);
  }
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::FormShow(TObject *Sender)
{
	if (mSettingsP == NULL)
  {
    ModalResult = mrCancel;
    return;
  }

	mUpperROMFilenames = new TStringList;
	mLastAddedROMDirectory = mSettingsP->RomsDirectory;

  ShowHint = mSettingsP->ShowHints;

  // Apply theme
	Color = mSettingsP->ThemeBackgroundColor;
  StringGridROMMapping->FixedColor = Color;
  Font->Name = "Amstrad CPC464 Regular";
  Font->Size = 6;
  Font->Color = mSettingsP->ThemeText1Color;
	for (int Loop=0; Loop < ComponentCount; Loop++)
	{
		if (Components[Loop]->Name.Pos("GroupBox") == 1)
		{
			((TGroupBox*)Components[Loop])->Font->Color = mSettingsP->ThemeText2Color;
		}
		else if (Components[Loop]->Name.Pos("Label") == 1)
		{
			((TLabel*)Components[Loop])->Font->Color = mSettingsP->ThemeText1Color;
		}
		else if (Components[Loop]->Name.Pos("ComboBox") == 1)
		{
			((TComboBox*)Components[Loop])->Font->Color = clBlack;
		}
		else if (Components[Loop]->Name.Pos("PanelButton") == 1)
		{
			((TPanel*)Components[Loop])->Color = mSettingsP->ThemeButtonColor;
			((TPanel*)Components[Loop])->Font->Color = mSettingsP->ThemeButtonTextColor;
		}
		else if (Components[Loop]->Name.Pos("RadioButton") == 1)
		{
			((TRadioButton*)Components[Loop])->Color = mSettingsP->ThemeButtonColor;
			((TRadioButton*)Components[Loop])->Font->Color = mSettingsP->ThemeText1Color;
		}
	}
	// Second pass to set objects inside groupboxes
	for (int Loop=0; Loop < ComponentCount; Loop++)
	{
		if (Components[Loop]->Name.Pos("CheckBox") == 1)
		{
			((TCheckBox*)Components[Loop])->Font->Color = mSettingsP->ThemeText1Color;
		}
	}

	//
	// List available ROMs
	//
	mXMEMRomP = NULL;
	ComboBoxMF2Rom->Clear();
	ComboBoxMF2Rom->Items->Add(DefaultMultiface2RomName);

	RadioButtonXMASSCreate512Mo->Checked = true;

#ifdef ENABLE_MULTIFACE2
	//
	// Multiface 2
	//
	AnsiString MF2Path = ExpandFileName(mSettingsP->Multiface2Directory);
	if (DirectoryExists(MF2Path))
	{
		TSearchRec F;
		if (FindFirst(MF2Path + "*.*", faAnyFile, F) == 0)
		{
			int findresult;
			do
			{
				// Get file size
				int FileSize = 0;
				int iFileHandle = FileOpen(MF2Path + F.Name, fmOpenRead | fmShareDenyNone);
				if (iFileHandle != -1)
				{
					// Get file size
					FileSize = FileSeek(iFileHandle, 0, 2);
					FileClose(iFileHandle);
				}

				if ( (FileSize == MULTIFACE2_ROM_SIZE) || (FileSize == (MULTIFACE2_ROM_SIZE + AMSDOS_HEADER_SIZE)) )
				{
					ComboBoxMF2Rom->Items->Add(F.Name);
				}

				findresult = FindNext(F);
			}
			while (findresult == 0);
		}
	}
#endif /* ENABLE_MULTIFACE2 */

	//
	// Roms mapping
	//
	StringGridROMMapping->RowCount = NB_ROMS;
	StringGridROMMapping->ColWidths[0] = 100;
	StringGridROMMapping->ColWidths[1] = StringGridROMMapping->Width - StringGridROMMapping->ColWidths[0];
	StringGridROMMapping->Cells[0][0] = "LowerROM";
	for (int loop=0; loop < NB_UPPER_ROMS; loop++)
	{
		AnsiString Header = "UpperROM ";
		if (loop < 10) Header += " ";
		StringGridROMMapping->Cells[0][loop+1] = Header + AnsiString(loop);
	}

	PageControlPeripherals->ActivePage = TabSheetMultiface2;

	// List available Settings
	UpdateAvailableSettings("");

	// Display settings
	DisplaySettings(mSettingsP);

	ActiveControl = StringGridROMMapping;

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::FormHide(TObject *Sender)
{
	delete mUpperROMFilenames;

	delete [] mXMEMRomP;

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::PanelButtonApplyClick(TObject *Sender)
{
	if (mXMEMRomModified == true)
	{
		UpdateXMEMROM();
	}

  // Apply new settings
  StoreSettings(mSettingsP);

  ModalResult = mrOk;

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonCancelClick(TObject *Sender)
{
	if (mXMEMRomModified == true)
	{
		AnsiString ROMFilename = mXMemFilename;
		if (ROMFilename == mSettingsP->XMemROMFilename)
		{
			if (ROMFilename != NewXMEMRomName)
			{
				if (Application->MessageBox(_T("Content of X-Mem image has been modified.\r\n\r\nAre you sure to loose updates?"),
																		((String)ROMFilename).c_str(),
																		MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
				{
					ModalResult = mrCancel;
				}
			}
			else
			{
				UpdateXMEMROM();
				ModalResult = mrCancel;
			}
		}
		else
		{
			UpdateXMEMROM();
			ModalResult = mrCancel;
		}
	}
	else
	{
		ModalResult = mrCancel;
	}

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::FormResize(TObject *Sender)
{
	StringGridROMMapping->ColWidths[1] = StringGridROMMapping->Width - StringGridROMMapping->ColWidths[0];

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::StringGridROMMappingMouseDown(
			TObject *Sender, TMouseButton Button, TShiftState Shift, int X,
      int Y)
{
	// Get selected row
  int SelectedCol;
	int SelectedRow;
  StringGridROMMapping->MouseToCell(X, Y, SelectedCol, SelectedRow);
  if (SelectedRow != -1)
  {
    StringGridROMMapping->Row = SelectedRow;
    UpdateAvailableROMList(SelectedRow);
  }

  NOT_USED(Sender);
  NOT_USED(Button);
  NOT_USED(Shift);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::FillROMMapping(void)
{
	//
	// Lower ROM
	//
	if ( (CheckBoxUseXMEM->Checked == false) || (CheckBoxBootXMEM->Checked == false) )
	{
		if (mLowerROMFilename.IsEmpty() == false)
		{
			StringGridROMMapping->Cells[1][0] = ExtractFileName(mLowerROMFilename);
		}
		else
		{
			StringGridROMMapping->Cells[1][0] = DefaultOSRomName;
		}
	}
	else
	{
		// Is X-Mem Slot 7 not blank ?
		if (mEmulatorP->IsBlankROM(mXMEMRomP + (ROM_SIZE * 7), ROM_SIZE) == false)
		{
			StringGridROMMapping->Cells[1][0] = "X-Mem LowerROM";
		}
		else
		{
			StringGridROMMapping->Cells[1][0] = "";
		}
	}

	//
	// Upper ROMs
	//
	for (int loop=0; loop < NB_UPPER_ROMS; loop++)
	{
		AnsiString ROMFilename = ExtractFileName(mUpperROMFilenames->Strings[loop]);
		AnsiString ROMName = "";
		if (ROMFilename.IsEmpty() == false)
		{
			if (ROMFilename != EmptyRomName)
			{
				ROMName = mEmulatorP->GetROMName(mUpperROMFilenames->Strings[loop]);
				if (ROMName.IsEmpty() == true)
				{
					ROMName = ROMFilename;
				}
			}
		}

		if (CheckBoxUseXMEM->Checked == false)
		{
			if (ROMFilename.IsEmpty() == false)
			{
				StringGridROMMapping->Cells[1][loop+1] = ROMName;
			}
			// Default ROM
			else
			{
				// BASIC ROM
				if (loop == 0)
				{
					StringGridROMMapping->Cells[1][loop+1] = DefaultBASICRomName;
				}
				// AMSDOS ROM
				else if (loop == 7)
				{
					StringGridROMMapping->Cells[1][loop+1] = DefaultAMSDOSRomName;
				}
				// Other ROMs
				else
				{
					StringGridROMMapping->Cells[1][loop+1] = "";
				}
			}
		}
		else
		{
			// AMSDOS ?
			if (loop == 7)
			{
				if (ROMFilename.IsEmpty() == false)
				{
					StringGridROMMapping->Cells[1][loop+1] = ROMName;
				}
				// Default AMSDOS ROM
				else
				{
					StringGridROMMapping->Cells[1][loop+1] = DefaultAMSDOSRomName;
				}
			}
			// BASIC ?
			else if ( (loop == 0) && (CheckBoxBootXMEM->Checked == false) )
			{
				if (ROMName.IsEmpty() == false)
				{
					StringGridROMMapping->Cells[1][loop+1] = ROMName;
				}
				// Default AMSDOS ROM
				else
				{
					StringGridROMMapping->Cells[1][loop+1] = DefaultBASICRomName;
				}
			}
			else if (mXMEMRomP)
			{
				StringGridROMMapping->Cells[1][loop+1] = mEmulatorP->GetROMName(mXMEMRomP + (ROM_SIZE * loop), ROM_SIZE);
			}
			else
			{
				StringGridROMMapping->Cells[1][loop+1] = "";
			}
		}
	}
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::UpdateAvailableROMList(int Index)
{
	if (Index < 0) return;

	ComboBoxAvailableROM->Clear();
	ComboBoxAvailableROM->Items->Add(EmptyRomName);

	bool XMEMRomNameAdded = false;

#ifdef USE_XMEM

	if (CheckBoxUseXMEM->Checked == true)
	{
		if (CheckBoxBootXMEM->Checked == false)
		{
			if ( (Index != 0) && (Index != 1) && (Index != 8) )
			{
				AnsiString ROMName = mEmulatorP->GetROMName(mXMEMRomP + (ROM_SIZE * (Index-1)), ROM_SIZE);
				if (ROMName.Length() > 0)
				{
					ComboBoxAvailableROM->Items->Add(XMEMRomName);
					XMEMRomNameAdded = true;
				}
			}
		}
		else
		{
			if (Index == 0)
			{
				// Is X-MEM Slot 7 not blank ?
				if (mEmulatorP->IsBlankROM(mXMEMRomP + (ROM_SIZE * 7), ROM_SIZE) == false)
				{
					ComboBoxAvailableROM->Items->Add(XMEMRomName);
					XMEMRomNameAdded = true;
				}
			}
			else if (Index != 8)
			{
				AnsiString ROMName = mEmulatorP->GetROMName(mXMEMRomP + (ROM_SIZE * (Index-1)), ROM_SIZE);
				if (ROMName.Length() > 0)
				{
					ComboBoxAvailableROM->Items->Add(XMEMRomName);
					XMEMRomNameAdded = true;
				}
			}
		}
	}

#endif /* USE_XMEM */

	//
	// Add Default ROMs
	//
	if (Index == 0) // Lower ROM
	{
		if ( (CheckBoxUseXMEM->Checked == false) || (CheckBoxBootXMEM->Checked == false) )
		{
			ComboBoxAvailableROM->Items->Add(DefaultOSRomName);
		}
	}
	else if (Index == 1) // Upper ROM 0
	{
		if ( (CheckBoxUseXMEM->Checked == false) || (CheckBoxBootXMEM->Checked == false) )
		{
			ComboBoxAvailableROM->Items->Add(DefaultBASICRomName);
		}
	}
	else if (Index == 8) // Upper ROM 7
	{
		ComboBoxAvailableROM->Items->Add(DefaultAMSDOSRomName);
	}
	else if (CheckBoxUseXMEM->Checked == false)
	{
		ComboBoxAvailableROM->Items->Add(DefaultAMSDOSRomName);
#ifdef USE_SILICON_DISC
		ComboBoxAvailableROM->Items->Add(DefaultSiliconDiscRomName);
#endif /* USE_SILICON_DISC */
	}

	//
	// Get ROM Folder
	//
	mSelectedROMDirectory = mLastAddedROMDirectory;
	if (XMEMRomNameAdded == false)
	{
		AnsiString ROMFilename;
		if (Index == 0)
		{
			ROMFilename = mLowerROMFilename;
		}
		else
		{
			ROMFilename = mUpperROMFilenames->Strings[Index-1];
		}

		if ( (ROMFilename != EmptyRomName)
				 && (ROMFilename != DefaultOSRomName)
				 && (ROMFilename != DefaultBASICRomName)
				 && (ROMFilename != DefaultAMSDOSRomName)
				 && (ROMFilename != DefaultSiliconDiscRomName) )
		{
			mSelectedROMDirectory = ExtractFilePath(ExpandFileName(mSettingsP->RomsDirectory + ROMFilename));
		}
	}

	//
	// Add list of ROMs
	//
	if (DirectoryExists(mSelectedROMDirectory))
	{
		TSearchRec F;
		if (FindFirst(mSelectedROMDirectory + "*.*", faAnyFile, F) == 0)
		{
			int findresult;
			do
			{
				// Get file size
				int FileSize = 0;
				int iFileHandle = FileOpen(mSelectedROMDirectory + F.Name, fmOpenRead | fmShareDenyNone);
				if (iFileHandle != -1)
				{
					// Get file size
					FileSize = FileSeek(iFileHandle, 0, 2);
					FileClose(iFileHandle);
				}

				// ROM File ?
				if ( (FileSize > 0)  && (FileSize <= (ROM_SIZE + AMSDOS_HEADER_SIZE)) )
				{
					ComboBoxAvailableROM->Items->Add(F.Name);
				}

				findresult = FindNext(F);
			}
			while (findresult == 0);
		}
	}

	// Upper ROM ?
	if (Index > 0)
	{
		// Add temporary Upper ROM
		AnsiString UpperROM = ExtractFileName(mUpperROMFilenames->Strings[Index-1]);
		if ( (UpperROM.IsEmpty() == false) && (UpperROM != EmptyRomName) )
		{
			// Temporary ROM ?
			if (ComboBoxAvailableROM->Items->IndexOf(UpperROM) == -1)
			{
				ComboBoxAvailableROM->Items->Add(UpperROM);
			}
		}
	}

	//
	// Select current ROM
	//
	AnsiString CurrentROM = StringGridROMMapping->Cells[1][Index];
	if (Index > 0)
	{
		CurrentROM = ExtractFileName(mUpperROMFilenames->Strings[Index-1]);
	}
	if (CurrentROM.IsEmpty() == true)
	{
		CurrentROM = EmptyRomName;
	}
	mSelectedROMFilename = CurrentROM;


	if (CheckBoxUseXMEM->Checked == true)
	{
		if (CheckBoxBootXMEM->Checked == false)
		{
			if ( (Index != 0) && (Index != 1) && (Index != 8) )
			{
				if (XMEMRomNameAdded == true)
				{
					ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(XMEMRomName);
				}
				else
				{
					ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(EmptyRomName);
				}
			}
			else
			{
				ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(CurrentROM);
			}
		}
		else
		{
			if (Index != 8)
			{
				if (XMEMRomNameAdded == true)
				{
					ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(XMEMRomName);
				}
				else
				{
					ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(EmptyRomName);
				}
			}
			else
			{
				ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(CurrentROM);
			}
		}
	}
	else
	{
		ComboBoxAvailableROM->ItemIndex = ComboBoxAvailableROM->Items->IndexOf(CurrentROM);
	}
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::UpdateAvailableSettings(AnsiString SelectedFilename)
{
	AnsiString SettingsPath = ExpandFileName(mSettingsP->SettingsDirectory);
	AnsiString SelectedSettings = "";
	ComboBoxSettings->Clear();
	if (DirectoryExists(SettingsPath))
	{
		TSearchRec F;
		if (FindFirst(SettingsPath + "*.ini", faAnyFile, F) == 0)
		{
			int findresult;
			do
			{
				AnsiString Settings = AnsiString(F.Name).SubString(1,
																												AnsiString(F.Name).Pos(SETTINGS_INI_EXT) - 1);
				ComboBoxSettings->Items->Add(Settings);
				if (F.Name == SelectedFilename)
				{
          SelectedSettings = Settings;
        }
        findresult = FindNext(F);
      }
      while (findresult == 0);
    }

		// Select settings
		if (SelectedSettings.IsEmpty() == false)
		{
			ComboBoxSettings->ItemIndex = ComboBoxSettings->Items->IndexOf(SelectedSettings);
		}
	}
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::ComboBoxAvailableROMChange(
			TObject *Sender)
{
	AnsiString NewROM = ComboBoxAvailableROM->Text;
	int Index = StringGridROMMapping->Row;

	bool IsXMEMRom = false;
#ifdef USE_XMEM
	if (CheckBoxUseXMEM->Checked == true)
	{
		if (CheckBoxBootXMEM->Checked == false)
		{
			if ( (Index != 0) && (Index != 1) && (Index != 8) )
			{
				IsXMEMRom = true;
			}
		}
		else
		{
			if (Index != 8)
			{
				IsXMEMRom = true;
			}
		}
	}
#endif /* USE_XMEM */

	if (IsXMEMRom == false)
	{
		// LowerROM ?
		if (Index == 0)
		{
			mLowerROMFilename = NewROM;
		}
		else
		{
			mUpperROMFilenames->Strings[Index-1] = NewROM;
		}
		mSelectedROMFilename = NewROM;
	}
	else
	{
		// Translate lower ROM to X-MEM slot
		if (Index == 0) Index = 8;

		mSelectedROMFilename = XMEMRomName;

		if (NewROM == EmptyRomName)
		{
			// Erase selected ROM
			memset(mXMEMRomP + (ROM_SIZE * (Index - 1)), 0xff, ROM_SIZE);
			// Signal ROM has been modifed
			mXMEMRomModified = true;
		}
		else
		{
			// Load ROM
			AnsiString ROMPath = ExpandFileName(mSettingsP->RomsDirectory);
			tUChar* RomP = mEmulatorP->LoadROM(ROMPath + NewROM);
			if (RomP)
			{
				memcpy(mXMEMRomP + (ROM_SIZE * (Index - 1)), RomP, ROM_SIZE);
				delete [] RomP;

				// Signal ROM has been modifed
				mXMEMRomModified = true;
			}
		}
	}

	FillROMMapping();

	ActiveControl = StringGridROMMapping;

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TFormEmulatorSettings::PanelButtonROMFileClick(TObject *Sender)
{
	int Index = StringGridROMMapping->Row;
	AnsiString ROMFilename = mSelectedROMFilename;
	AnsiString ROMPath = mSelectedROMDirectory;
	if (FileExists(ROMPath + ROMFilename) == false)
	{
		ROMFilename = "";
	}

	OpenDialog->Title = "Select ROM File...";
	OpenDialog->FileName = ROMFilename;
	OpenDialog->InitialDir = ROMPath;
	OpenDialog->Filter = ROM_FILTER;
	OpenDialog->DefaultExt = ROM_EXT;
	OpenDialog->Options = OpenDialog->Options << ofFileMustExist;
	if (OpenDialog->Execute() == true)
	{
		SetCurrentDir(mSettingsP->RomsDirectory);
		mLastAddedROMDirectory = ExtractFilePath(OpenDialog->FileName);
		AnsiString NewROM = ExtractRelativePath(mSettingsP->RomsDirectory,
																						mLastAddedROMDirectory);
		NewROM += ExtractFileName(OpenDialog->FileName);


		bool IsXMEMRom = false;
#ifdef USE_XMEM
		if (CheckBoxUseXMEM->Checked == true)
		{
			if (CheckBoxBootXMEM->Checked == false)
			{
				if ( (Index != 0) && (Index != 1) && (Index != 8) )
				{
					IsXMEMRom = true;
				}
			}
			else
			{
				if (Index != 8)
				{
					IsXMEMRom = true;
				}
			}
		}
#endif /* USE_XMEM */

		if (IsXMEMRom == false)
		{
			// LowerROM ?
			if (Index == 0)
			{
				mLowerROMFilename = NewROM;
			}
			else
			{
				mUpperROMFilenames->Strings[Index-1] = NewROM;
			}
		}
		else
		{
			// Translate lower ROM to X-MEM slot
			if (Index == 0) Index = 8;

			if (NewROM == EmptyRomName)
			{
				// Erase selected ROM
				memset(mXMEMRomP + (ROM_SIZE * (Index - 1)), 0xFF, ROM_SIZE);
				// Signal ROM has been modifed
				mXMEMRomModified = true;
			}
			else
			{
				// Load ROM
				tUChar* RomP = mEmulatorP->LoadROM(mSettingsP->RomsDirectory + NewROM);
				if (RomP)
				{
					memcpy(mXMEMRomP + (ROM_SIZE * (Index - 1)), RomP, ROM_SIZE);
					delete [] RomP;

					// Signal ROM has been modifed
					mXMEMRomModified = true;
				}
			}
		}

		FillROMMapping();
		UpdateAvailableROMList(StringGridROMMapping->Row);

		ActiveControl = StringGridROMMapping;
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::ComboBoxDrawItem(TWinControl *Control,
          int Index, TRect &Rect, TOwnerDrawState State)
{
	TComboBox* ComboBox = (TComboBox*)Control;
	TCanvas* Canvas = ComboBox->Canvas;

  if (State.Contains(odSelected))
  {
    Canvas->Brush->Color = clHighlight;
    Canvas->Font->Color = clWhite;
  }
	else
  {
    Canvas->Brush->Color = clWhite;
    Canvas->Font->Color = clBlack;
  }

  // Draw cell
  Canvas->FillRect(Rect);
	AnsiString Text = ComboBox->Items->Strings[Index];
	if (Text.Length() > 0)
	{
		int TextHeight = Canvas->TextHeight(Text);
		int TextPos = (ComboBox->ItemHeight - TextHeight) / 2;
		Canvas->TextOut(Rect.Left+5, Rect.Top+TextPos, Text);
	}
	if (State.Contains(odFocused))
	{
    Canvas->DrawFocusRect(Rect);
  }

  NOT_USED(Index);
  NOT_USED(Control);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::StringGridROMMappingSelectCell(
			TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
	UpdateAvailableROMList(ARow);

  NOT_USED(Sender);
  NOT_USED(ACol);
  NOT_USED(CanSelect);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::StringGridROMMappingKeyDown(
			TObject *Sender, WORD &Key, TShiftState Shift)
{
	if (StringGridROMMapping->Focused() == true)
	{
    // Select first ROM of the available ROM list
    if ( (Key == VK_DELETE) || (Key == VK_BACK) )
    {
      ComboBoxAvailableROM->ItemIndex = 0;
      ComboBoxAvailableROMChange(Sender);
    }
  }

  NOT_USED(Shift);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::StringGridDrawCell(TObject *Sender,
					int ACol, int ARow, TRect &Rect, TGridDrawState State)
{
	TStringGrid* StringGrid = (TStringGrid*)Sender;

  // Fixed column ?
  if (ACol == 0)
  {
		StringGrid->Canvas->Brush->Color = Color;
		StringGrid->Canvas->Font->Color = mSettingsP->ThemeText2Color;
  }
  else
  {
    if (State.Contains(gdSelected))
    {
			StringGrid->Canvas->Brush->Color = clHighlight;
			StringGrid->Canvas->Font->Color = clWhite;
    }
    else
    {
			StringGrid->Canvas->Brush->Color = Color;
			StringGrid->Canvas->Font->Color = Font->Color;
    }
  }

  // Draw cell
	StringGrid->Canvas->FillRect(Rect);
	AnsiString Content = StringGrid->Cells[ACol][ARow];
	if (Content.Length() > 0)
	{
		int TextHeight = StringGrid->Canvas->TextHeight(Content);
		int TextPos = (StringGrid->RowHeights[ARow] - TextHeight) / 2;
		StringGrid->Canvas->TextOut(Rect.Left+5,
																Rect.Top+TextPos,
																Content);
	}
	if (State.Contains(gdFocused))
	{
    StringGrid->Canvas->DrawFocusRect(Rect);
  }

  NOT_USED(ARow);
  NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::ComboBoxDevicesChange(TObject *Sender)
{
	// Floppy drive use
  switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
  {
    case CPC_MODEL_464_UK:
		case CPC_MODEL_464_FR:
		case CPC_MODEL_464_SP:
    {
      CheckBoxUseFloppyDrive->Checked = false;
    }
    break;

    default:
    {
      CheckBoxUseFloppyDrive->Checked = true;
    }
  }

  // 64Ko expansion
  switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
  {
    case CPC_MODEL_464_UK:
    case CPC_MODEL_464_FR:
    case CPC_MODEL_464_SP:
    case CPC_MODEL_664_UK:
    case CPC_MODEL_664_FR:
		{
      CheckBoxUse64kMemoryExtension->Checked = false;
      CheckBoxUse64kMemoryExtension->Enabled = true;
    }
		break;

    default:
    {
      CheckBoxUse64kMemoryExtension->Checked = true;
      CheckBoxUse64kMemoryExtension->Enabled = false;
    }
  }

  // Default AMSDOS
	switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
	{
    case CPC_MODEL_464_UK:
		case CPC_MODEL_464_FR:
    case CPC_MODEL_464_SP:
    {
			// Remove Default AMSDOS
			if (mUpperROMFilenames->Strings[7] == DefaultAMSDOSRomName)
      {
				mUpperROMFilenames->Strings[7] = EmptyRomName;
      }
    }
    break;

    default:
    {
      // Add Default AMSDOS
			if (mUpperROMFilenames->Strings[7] == EmptyRomName)
      {
        mUpperROMFilenames->Strings[7] = DefaultAMSDOSRomName;
      }
    }
  }

  // Brand name
  switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
  {
		case CPC_MODEL_464_SP:
    {
      // Amstrad ONLY
      ComboBoxBrands->ItemIndex = 0;
			ComboBoxBrands->Enabled = false;
    }
    break;

    default:
    {
      ComboBoxBrands->Enabled = true;
    }
  }

	// CRTC Type
  switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
  {
    case CPC_MODEL_664_UK:
    case CPC_MODEL_664_FR:
    {
			// CRTC0 Only
      ComboBoxCRTCType->ItemIndex = 0;
      ComboBoxCRTCType->Enabled = false;
		}
    break;

    default:
    {
      ComboBoxCRTCType->Enabled = true;
    }
  }

#ifdef USE_RAM_4MB
	if (CheckBoxUse4MMemoryExtension->Checked == true)
	{
		CheckBoxUse64kMemoryExtension->Enabled = false;
		CheckBoxUse256kMemoryExtension->Enabled = false;
#ifdef USE_SILICON_DISC
		CheckBoxUse256kSiliconDisc->Enabled = false;
#endif /* USE_SILICON_DISC */
	}
#endif /* USE_RAM_4MB */
#ifdef USE_XMEM
	if (CheckBoxUseXMEM->Checked == true)
	{
		CheckBoxUse64kMemoryExtension->Enabled = false;
		CheckBoxUse256kMemoryExtension->Enabled = false;
#ifdef USE_SILICON_DISC
		CheckBoxUse256kSiliconDisc->Enabled = false;
#endif /* USE_SILICON_DISC */
	}
#endif /* USE_XMEM */

	// Update ROM Mapping
	FillROMMapping();

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::ComboBoxDevicesDrawItem(TWinControl *Control,
					int Index, TRect &Rect, TOwnerDrawState State)
{
  TCanvas* Canvas = ComboBoxDevices->Canvas;

  if (State.Contains(odSelected))
  {
    Canvas->Brush->Color = clHighlight;
    Canvas->Font->Color = clWhite;
  }
  else
  {
    Canvas->Brush->Color = clWhite;
    switch (Devices[Index].CPCModel)
    {
      case CPC_MODEL_464_UK:
      case CPC_MODEL_464_FR:
      case CPC_MODEL_464_SP:
      {
        Canvas->Font->Color = clRed;
      }
      break;

      case CPC_MODEL_664_UK:
      case CPC_MODEL_664_FR:
      {
        Canvas->Font->Color = clGreen;
      }
      break;

      case CPC_MODEL_6128_UK:
      case CPC_MODEL_6128_FR:
      case CPC_MODEL_6128_SP:
      {
        Canvas->Font->Color = clBlue;
      }
      break;

      default:
      {
        Canvas->Font->Color = clBlack;
      }
		}
  }

  // Draw cell
  Canvas->FillRect(Rect);
  AnsiString Text = ComboBoxDevices->Items->Strings[Index];
  int TextHeight = Canvas->TextHeight(Text);
  int TextPos = (ComboBoxDevices->ItemHeight - TextHeight) / 2;
  Canvas->TextOut(Rect.Left+5, Rect.Top+TextPos, Text);
  if (State.Contains(odFocused))
  {
    Canvas->DrawFocusRect(Rect);
  }

  NOT_USED(Control);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::ComboBoxBrandsDrawItem(TWinControl *Control,
          int Index, TRect &Rect, TOwnerDrawState State)
{
  TCanvas* Canvas = ComboBoxBrands->Canvas;

  if (State.Contains(odSelected))
  {
    Canvas->Brush->Color = clHighlight;
    Canvas->Font->Color = clWhite;
  }
  else
  {
    Canvas->Brush->Color = clWhite;
    Canvas->Font->Color = clBlack;
  }

  // Draw cell
  Canvas->FillRect(Rect);
  AnsiString Text = ComboBoxBrands->Items->Strings[Index];
  int TextHeight = Canvas->TextHeight(Text);
  int TextPos = (ComboBoxBrands->ItemHeight - TextHeight) / 2;
  Canvas->TextOut(Rect.Left+5, Rect.Top+TextPos, Text);
  if (State.Contains(odFocused))
	{
    Canvas->DrawFocusRect(Rect);
  }

  NOT_USED(Index);
  NOT_USED(Control);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::CheckBoxUseFloppyDriveClick(TObject *Sender)
{
	if (CheckBoxUseFloppyDrive->Checked == true)
	{
		CheckBoxUseFastFDC->Enabled = true;

		// Add Default AMSDOS
		if (StringGridROMMapping->Cells[1][8].IsEmpty() == true)
		{
			StringGridROMMapping->Cells[1][8] = DefaultAMSDOSRomName;
			mUpperROMFilenames->Strings[7] = DefaultAMSDOSRomName;
		}
	}
  else
  {
    CheckBoxUseFastFDC->Checked = false;
    CheckBoxUseFastFDC->Enabled = false;
  }

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::ComboBoxCRTCTypeDrawItem(TWinControl *Control,
          int Index, TRect &Rect, TOwnerDrawState State)
{
  TCanvas* Canvas = ComboBoxCRTCType->Canvas;

  if (State.Contains(odSelected))
  {
		Canvas->Brush->Color = clHighlight;
    Canvas->Font->Color = clWhite;
  }
  else
  {
    Canvas->Brush->Color = clWhite;
    Canvas->Font->Color = clBlack;
  }

  // Draw cell
  Canvas->FillRect(Rect);
  AnsiString Text = ComboBoxCRTCType->Items->Strings[Index];
  int TextHeight = Canvas->TextHeight(Text);
  int TextPos = (ComboBoxCRTCType->ItemHeight - TextHeight) / 2;
  Canvas->TextOut(Rect.Left+5, Rect.Top+TextPos, Text);
  if (State.Contains(odFocused))
  {
    Canvas->DrawFocusRect(Rect);
  }

  NOT_USED(Control);
  NOT_USED(Index);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::CheckBoxUse256kSiliconDiscClick(TObject *Sender)
{
  if (CheckBoxUse256kSiliconDisc->Focused() == true)
  {
    UpdateSiliconDisc();
  }

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::UpdateSiliconDisc(void)
{
  if (CheckBoxUse256kSiliconDisc->Checked == true)
	{
    int loop;
    // Find Silicon Disc ROM
    for (loop=1; loop < NB_UPPER_ROMS; loop++)
    {
      if (loop == 7) continue; // Already treated

      AnsiString ROM = StringGridROMMapping->Cells[1][loop+1];
      if (ROM == DefaultSiliconDiscRomName)
      {
        break;
      }
    }

    // Find empty ROM location for SiliconDisk
    if (loop == NB_UPPER_ROMS)
    {
      for (loop=1; loop < NB_UPPER_ROMS; loop++)
      {
        if (loop == 7) continue; // Already treated

        AnsiString ROM = StringGridROMMapping->Cells[1][loop+1];
        if (ROM == DefaultSiliconDiscRomName)
        {
          break;
        }
        else if (ROM.IsEmpty() == true)
        {
					mUpperROMFilenames->Strings[loop] = DefaultSiliconDiscRomName;
					StringGridROMMapping->Cells[1][loop+1] = DefaultSiliconDiscRomName;
          break;
        }
      }
    }

    // No empty location
    if (loop == NB_UPPER_ROMS)
    {
      Application->MessageBox(_T("No available ROM location for Silicon Disc."), _T("ROM"), MB_OK);
      CheckBoxUse256kSiliconDisc->Checked = false;
    }
  }
	else
  {
    // Remove Silicon Disc ROM
    for (int loop=1; loop < NB_UPPER_ROMS; loop++)
    {
      if (loop == 7) continue; // Already treated

      AnsiString ROM = StringGridROMMapping->Cells[1][loop+1];
      if (ROM == DefaultSiliconDiscRomName)
      {
				mUpperROMFilenames->Strings[loop] = EmptyRomName;
				StringGridROMMapping->Cells[1][loop+1] = "";
        break;
      }
    }
  }

	UpdateAvailableROMList(StringGridROMMapping->Row);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::CheckBoxUse4MMemoryExtensionClick(
      TObject *Sender)
{
#ifdef USE_RAM_4MB

  if (CheckBoxUse4MMemoryExtension->Checked == true)
  {
    CheckBoxUse64kMemoryExtension->Enabled = false;
    CheckBoxUse256kMemoryExtension->Checked = false;
    CheckBoxUse256kMemoryExtension->Enabled = false;
#ifdef USE_SILICON_DISC
    CheckBoxUse256kSiliconDisc->Checked = false;
    CheckBoxUse256kSiliconDisc->Enabled = false;
#endif /* USE_SILICON_DISC */
  }
  else
  {
		if (CheckBoxUseXMEM->Checked == false)
		{
			CheckBoxUse256kMemoryExtension->Checked = false;
			CheckBoxUse256kMemoryExtension->Enabled = true;
			CheckBoxUse256kSiliconDisc->Checked = false;
			CheckBoxUse256kSiliconDisc->Enabled = true;
		}

    // 64Ko expansion
    switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
    {
      case CPC_MODEL_464_UK:
      case CPC_MODEL_464_FR:
      case CPC_MODEL_464_SP:
      case CPC_MODEL_664_UK:
      case CPC_MODEL_664_FR:
      {
        CheckBoxUse64kMemoryExtension->Checked = false;
        CheckBoxUse64kMemoryExtension->Enabled = true;
      }
      break;

      default:
      {
        CheckBoxUse64kMemoryExtension->Checked = true;
        CheckBoxUse64kMemoryExtension->Enabled = false;
      }
    }
  }

	UpdateSiliconDisc();

#endif /* USE_RAM_4MB */

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::CheckBoxUseXMEMClick(TObject *Sender)
{
#ifdef USE_XMEM

	if (CheckBoxUseXMEM->Checked == true)
	{
		CheckBoxUse64kMemoryExtension->Enabled = false;
		CheckBoxUse256kMemoryExtension->Checked = false;
		CheckBoxUse256kMemoryExtension->Enabled = false;
#ifdef USE_SILICON_DISC
		CheckBoxUse256kSiliconDisc->Checked = false;
		CheckBoxUse256kSiliconDisc->Enabled = false;
#endif /* USE_SILICON_DISC */
	}
	else
	{
		if (CheckBoxUse4MMemoryExtension->Checked == false)
		{
			CheckBoxUse256kMemoryExtension->Checked = false;
			CheckBoxUse256kMemoryExtension->Enabled = true;
			CheckBoxUse256kSiliconDisc->Checked = false;
			CheckBoxUse256kSiliconDisc->Enabled = true;
		}

		// 64Ko expansion
		switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
		{
			case CPC_MODEL_464_UK:
			case CPC_MODEL_464_FR:
			case CPC_MODEL_464_SP:
			case CPC_MODEL_664_UK:
			case CPC_MODEL_664_FR:
			{
				CheckBoxUse64kMemoryExtension->Checked = false;
				CheckBoxUse64kMemoryExtension->Enabled = true;
			}
			break;

			default:
			{
				CheckBoxUse64kMemoryExtension->Checked = true;
				CheckBoxUse64kMemoryExtension->Enabled = false;
			}
		}
	}

	CheckBoxBootXMEM->Enabled = CheckBoxUseXMEM->Checked;

	FillROMMapping();
	UpdateSiliconDisc();
	UpdateAvailableROMList(StringGridROMMapping->Row);

#endif /* USE_XMEM */

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::CheckBoxBootXMEMClick(TObject *Sender)
{
#ifdef USE_XMEM

	FillROMMapping();
	UpdateAvailableROMList(StringGridROMMapping->Row);

#endif /* USE_XMEM */

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::PanelButtonSettingsSaveClick(TObject *Sender)
{
  AnsiString NewSettingsFilename = "";

  SaveDialog->Title = "Save settings...";
  SaveDialog->FileName = "";
  SaveDialog->InitialDir = mSettingsP->SettingsDirectory;
	SaveDialog->Filter = SETTINGS_FILTER;
  SaveDialog->DefaultExt = SETTINGS_INI_EXT;
  if (SaveDialog->Execute() == true)
  {
    // Prepare settings file
    NewSettingsFilename = SaveDialog->FileName;
    TSettings *NewSettings = new TSettings(NewSettingsFilename);
    StoreSettings(NewSettings);
    NewSettings->SaveEmulatorSettings();
    delete NewSettings;
  }

  UpdateAvailableSettings(ExtractFileName(NewSettingsFilename));

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::ComboBoxSettingsChange(
      TObject *Sender)
{
  AnsiString Filename = mSettingsP->SettingsDirectory +  ComboBoxSettings->Text + SETTINGS_INI_EXT;

  // Read settings file
  TSettings *NewSettings = new TSettings(Filename);
  DisplaySettings(NewSettings);
  delete NewSettings;

  ActiveControl = StringGridROMMapping;

  NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::ComboBoxSettingsDrawItem(
      TWinControl *Control, int Index, TRect &Rect, TOwnerDrawState State)
{
  TCanvas* Canvas = ComboBoxSettings->Canvas;

  if (State.Contains(odSelected))
	{
    Canvas->Brush->Color = clHighlight;
    Canvas->Font->Color = clWhite;
  }
  else
  {
    Canvas->Brush->Color = clWhite;
    Canvas->Font->Color = clBlack;
  }

  // Draw cell
  Canvas->FillRect(Rect);
  AnsiString Text = ComboBoxSettings->Items->Strings[Index];
  int TextHeight = Canvas->TextHeight(Text);
  int TextPos = (ComboBoxSettings->ItemHeight - TextHeight) / 2;
  Canvas->TextOut(Rect.Left+5, Rect.Top+TextPos, Text);
  if (State.Contains(odFocused))
  {
    Canvas->DrawFocusRect(Rect);
  }

  NOT_USED(Index);
  NOT_USED(Control);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::StoreSettings(TSettings* SettingsP)
{
  //
  // Update new settings
  //
  SettingsP->CPCDevice = Devices[ComboBoxDevices->ItemIndex].CPCModel;
  SettingsP->CPCBrand = ComboBoxBrands->ItemIndex;
  SettingsP->CRTCType = ComboBoxCRTCType->ItemIndex;
  SettingsP->UseFloppyDrive = CheckBoxUseFloppyDrive->Checked;
  SettingsP->UseFastFDC = CheckBoxUseFastFDC->Checked;
  SettingsP->Use64kMemoryExtension = CheckBoxUse64kMemoryExtension->Checked;
  SettingsP->Use256kMemoryExtension = CheckBoxUse256kMemoryExtension->Checked;
  SettingsP->Use256kSiliconDisc = CheckBoxUse256kSiliconDisc->Checked;
  SettingsP->Use4MMemoryExtension = CheckBoxUse4MMemoryExtension->Checked;
	SettingsP->UseTechniMusique = CheckBoxUseTechniMusique->Checked;
  SettingsP->UsePlayCity = CheckBoxUsePlayCity->Checked;
  SettingsP->UseDigiblaster = CheckBoxUseDigiblaster->Checked;
	SettingsP->UseMultiface2 = CheckBoxUseMultiface2->Checked;
	SettingsP->UseXMEM = CheckBoxUseXMEM->Checked;
	SettingsP->BootXMEM = (CheckBoxUseXMEM->Checked == true) ? CheckBoxBootXMEM->Checked : false;
	SettingsP->UseXMEM_SST = RadioButtonXMEM_SST->Checked;
	SettingsP->XMemDirectory = mXMemDirectory;
	SettingsP->XMemROMFilename = mXMemFilename;
	SettingsP->UseXMass = CheckBoxUseXMASS->Checked;
	SettingsP->XMassFilename = mXMassFilename;
	SettingsP->XMassDirectory = mXMassDirectory;

	//
  // Apply new ROM mapping
	//
	if (CheckBoxUseXMEM->Checked == false)
	{
		// Lower ROM
		AnsiString NewROM = StringGridROMMapping->Cells[1][0];
		SettingsP->LowerROMFilename = NewROM;
		// Upper ROM
		NewROM = StringGridROMMapping->Cells[1][1];
		SettingsP->UpperROMFilename[0] = NewROM;
	}
	// All others
	for (int loop=1; loop < NB_UPPER_ROMS; loop++)
	{
    AnsiString NewROM = mUpperROMFilenames->Strings[loop];
    if (NewROM.IsEmpty() == true)
    {
			SettingsP->UpperROMFilename[loop] = EmptyRomName;
    }
    else
    {
			SettingsP->UpperROMFilename[loop] = NewROM;
    }
  }

  //
  // Multiface 2 ROM
  //
	if (ComboBoxMF2Rom->Text == DefaultMultiface2RomName)
  {
    SettingsP->MF2ROMFilename = "";
  }
  else
  {
		SettingsP->MF2ROMFilename = ComboBoxMF2Rom->Text;
	}
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::DisplaySettings(TSettings* SettingsP)
{
	//
	// Read settings
	//
	for (int Index=0; Index < NB_DEVICES; Index++)
	{
		if (Devices[Index].CPCModel == SettingsP->CPCDevice)
		{
			ComboBoxDevices->ItemIndex = Index;
			break;
		}
	}

	//
	// Roms mapping
	//
	mLowerROMFilename = SettingsP->LowerROMFilename;
	mUpperROMFilenames->Clear();
	for (int loop=0; loop < NB_UPPER_ROMS; loop++)
	{
		mUpperROMFilenames->Add(SettingsP->UpperROMFilename[loop]);
	}

	//
	// Multiface 2 Rom
	//
	ComboBoxMF2Rom->ItemIndex = ComboBoxMF2Rom->Items->IndexOf(SettingsP->MF2ROMFilename);
	if (ComboBoxMF2Rom->ItemIndex == -1)
	{
		ComboBoxMF2Rom->ItemIndex = ComboBoxMF2Rom->Items->IndexOf(DefaultMultiface2RomName);
	}

	//
	// X-MEM
	//
#ifdef USE_XMEM
	mXMemDirectory = ExpandFileName(mSettingsP->XMemDirectory);
	mXMemFilename = SettingsP->XMemROMFilename;
	LabelXMemFilename->Caption = mXMemFilename;
	CheckBoxUseXMEM->Checked = SettingsP->UseXMEM;
	CheckBoxBootXMEM->Enabled = (SettingsP->UseXMEM == true) ? true : false;
	CheckBoxBootXMEM->Checked = SettingsP->BootXMEM;
	if (SettingsP->UseXMEM_SST == true)
	{
		RadioButtonXMEM_SST->Checked = true;
	}
	else
	{
		RadioButtonXMEM_Winbond->Checked = true;
	}
	// Load XMEM ROM
	mXMEMRomP = mEmulatorP->LoadXMEMROM(mXMemDirectory + mXMemFilename);
	PanelButtonXMemView->Visible = (mXMEMRomP != NULL) ? true : false;
	PanelButtonXMemRename->Visible = (mXMEMRomP != NULL) ? true : false;
	PanelButtonXMemDelete->Visible = (mXMEMRomP != NULL) ? true : false;
	if (mXMEMRomP == NULL)
	{
		// Create New X-MEM ROM
		mXMEMRomP = new tUChar[XMEM_ROM_SIZE];
		memset(mXMEMRomP, 0xff, XMEM_ROM_SIZE);
	}
	mXMEMRomModified = false;

#endif /* USE_XMEM */

	FillROMMapping();
	StringGridROMMapping->Row = 0;
	UpdateAvailableROMList(StringGridROMMapping->Row);

	ComboBoxBrands->ItemIndex = SettingsP->CPCBrand;
  ComboBoxCRTCType->ItemIndex = SettingsP->CRTCType;
  CheckBoxUseFloppyDrive->Checked = SettingsP->UseFloppyDrive;
  CheckBoxUse256kMemoryExtension->Checked = SettingsP->Use256kMemoryExtension;
#ifdef USE_SILICON_DISC
  CheckBoxUse256kSiliconDisc->Checked = SettingsP->Use256kSiliconDisc;
#endif /* USE_SILICON_DISC */
#ifdef USE_RAM_4MB
  CheckBoxUse4MMemoryExtension->Checked = SettingsP->Use4MMemoryExtension;
#endif /* USE_RAM_4MB */
  CheckBoxUseTechniMusique->Checked = SettingsP->UseTechniMusique;
  CheckBoxUsePlayCity->Checked = SettingsP->UsePlayCity;
  CheckBoxUseDigiblaster->Checked = SettingsP->UseDigiblaster;
  CheckBoxUseMultiface2->Checked = SettingsP->UseMultiface2;
#ifdef USE_XMASS
	CheckBoxUseXMASS->Checked = SettingsP->UseXMass;
	mXMassFilename = SettingsP->XMassFilename;
	mXMassDirectory = SettingsP->XMassDirectory;
	LabelXMassFilename->Caption = mXMassFilename;
#endif /* USE_XMASS */

  // Fast FDC
  if (CheckBoxUseFloppyDrive->Checked == true)
  {
    CheckBoxUseFastFDC->Enabled = true;
    CheckBoxUseFastFDC->Checked = SettingsP->UseFastFDC;
  }
	else
  {
		CheckBoxUseFastFDC->Enabled = false;
    CheckBoxUseFastFDC->Checked = false;
  }

  // 64Ko expansion
  switch (Devices[ComboBoxDevices->ItemIndex].CPCModel)
  {
    case CPC_MODEL_464_UK:
    case CPC_MODEL_464_FR:
    case CPC_MODEL_464_SP:
    case CPC_MODEL_664_UK:
    case CPC_MODEL_664_FR:
    {
      CheckBoxUse64kMemoryExtension->Checked = SettingsP->Use64kMemoryExtension;
      CheckBoxUse64kMemoryExtension->Enabled = true;
    }
    break;

    default:
    {
      CheckBoxUse64kMemoryExtension->Checked = true;
      CheckBoxUse64kMemoryExtension->Enabled = false;
    }
  }

  // Brand name limitations
  ComboBoxBrands->Enabled = (SettingsP->CPCDevice == CPC_MODEL_464_SP) ? false : true;
  if (SettingsP->CPCDevice == CPC_MODEL_464_SP)
  {
    ComboBoxBrands->ItemIndex = 0;
  }

  // CRTC Type
  if ( (SettingsP->CPCDevice == CPC_MODEL_664_UK)
       || (SettingsP->CPCDevice == CPC_MODEL_664_FR) )
  {
    // CRTC0 Only
    ComboBoxCRTCType->ItemIndex = 0;
    ComboBoxCRTCType->Enabled = false;
	}

#ifdef USE_RAM_4MB
  if (CheckBoxUse4MMemoryExtension->Checked == true)
  {
		CheckBoxUse64kMemoryExtension->Enabled = false;
    CheckBoxUse256kMemoryExtension->Enabled = false;
#ifdef USE_SILICON_DISC
    CheckBoxUse256kSiliconDisc->Enabled = false;
#endif /* USE_SILICON_DISC */
  }
#endif /* USE_RAM_4MB */
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonMouseDown(TObject *Sender,
          TMouseButton Button, TShiftState Shift, int X, int Y)
{
  ((TPanel*)Sender)->Color = mSettingsP->ThemeButtonTextColor;
	((TPanel*)Sender)->Font->Color = mSettingsP->ThemeButtonColor;

  NOT_USED(Button);
  NOT_USED(Shift);
  NOT_USED(X);
  NOT_USED(Y);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
{
  ((TPanel*)Sender)->Color = mSettingsP->ThemeButtonColor;
  ((TPanel*)Sender)->Font->Color = mSettingsP->ThemeButtonTextColor;

  NOT_USED(Button);
  NOT_USED(Shift);
  NOT_USED(X);
  NOT_USED(Y);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
  if (Key == VK_ESCAPE)
  {
    PanelButtonCancelClick(Sender);
  }
  else if (Key == VK_RETURN)
  {
    PanelButtonApplyClick(Sender);
  }
  else
  {
    // Nothing to do
  }

  NOT_USED(Shift);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::UpdateXMEMROM(void)
{
	// New file ?
	if (FileExists(mXMemDirectory + mXMemFilename) == false)
	{
		// Create file with new XMEM Content
		mXMemFilename = mEmulatorP->CreateNewXMEMROMFilename();
	}

	if (Application->MessageBox(_T("Content of X-Mem image has been modified.\r\n\r\nDo you want to save updates?"),
															((String)mXMemFilename).c_str(),
															MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
	{
		// New file ?
		if (FileExists(mXMemDirectory + mXMemFilename) == true)
		{
			// Delete file
			DeleteFile(mXMemDirectory + mXMemFilename);
		}

		// Create file with new XMEM Content
		int iHandle = FileCreate(mXMemDirectory + mXMemFilename);
		FileWrite(iHandle, mXMEMRomP, XMEM_ROM_SIZE);
		FileClose(iHandle);

		mXMEMRomModified = false;
	}
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::PanelButtonXMemDeleteClick(TObject *Sender)
{
	// Existing file ?
	if (FileExists(mXMemDirectory + mXMemFilename) == true)
	{
		if (Application->MessageBox(_T("Do you confirm deletion of this file ?"),
																((String)mXMemFilename).c_str(),
																MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
		{
			// Delete file
			DeleteFile(mXMemDirectory + mXMemFilename);

			mXMEMRomModified = false;

			mXMemFilename = NewXMEMRomName;
			LabelXMemFilename->Caption = mXMemFilename;
		}
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonXMemFileClick(TObject *Sender)
{
	OpenDialog->Title = "Select X-Mem File...";
	OpenDialog->FileName = mXMemFilename;
	OpenDialog->InitialDir = mXMemDirectory;
	OpenDialog->Filter = XMEM_FILTER;
	OpenDialog->DefaultExt = XMEM_EXT;
	OpenDialog->Options = OpenDialog->Options << ofFileMustExist;
	if (OpenDialog->Execute() == true)
	{
		mXMemDirectory = ExtractFilePath(OpenDialog->FileName);
		mXMemFilename = ExtractFileName(OpenDialog->FileName);
		// Update display
		LabelXMemFilename->Caption = mXMemFilename;

		mXMEMRomP = mEmulatorP->LoadXMEMROM(mXMemDirectory + mXMemFilename);
		mXMEMRomModified = false;

		PanelButtonXMemView->Visible = (mXMEMRomP != NULL) ? true : false;
		PanelButtonXMemRename->Visible = (mXMEMRomP != NULL) ? true : false;
		PanelButtonXMemDelete->Visible = (mXMEMRomP != NULL) ? true : false;

		// Update ROM display
		FillROMMapping();
		UpdateAvailableROMList(StringGridROMMapping->Row);
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonXMemCreateClick(TObject *Sender)
{
	OpenDialog->FileName = mEmulatorP->CreateNewXMEMROMFilename();
	OpenDialog->InitialDir = mXMemDirectory;
	OpenDialog->Filter = XMEM_FILTER;
	OpenDialog->DefaultExt = XMEM_EXT;
	if (OpenDialog->Execute() == true)
	{
		bool Create = true;

		// XMem file already exists ?
		if (FileExists(OpenDialog->FileName) == true)
		{
			if (Application->MessageBox(_T("File already exists. Are you sure to loose all your data ?"),
																	_T("X-Mem roms file"),
																	MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2) == IDNO)
			{
				Create = false;
			}
		}

		if (Create == true)
		{
			// Create New X-Mem ROM
			if (mXMEMRomP == NULL)
			{
				mXMEMRomP = new tUChar[XMEM_ROM_SIZE];
			}
			// Delete X-Mem content
			memset(mXMEMRomP, 0xff, XMEM_ROM_SIZE);
			mXMEMRomModified = true;

			// Create new file
			if (FileExists(OpenDialog->FileName) == false)
			{
				int iHandle = FileCreate(OpenDialog->FileName);
				FileWrite(iHandle, mXMEMRomP, XMEM_ROM_SIZE);
				FileClose(iHandle);
			}

			mXMemDirectory = ExtractFilePath(OpenDialog->FileName);
			mXMemFilename = ExtractFileName(OpenDialog->FileName);
			// Update display
			LabelXMemFilename->Caption = mXMemFilename;

			// Update ROM display
			FillROMMapping();
			UpdateAvailableROMList(StringGridROMMapping->Row);
		}
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonXMemViewClick(TObject *Sender)
{
	// For all X-MEM Roms
	AnsiString FileContent;
	for (int Loop=0; Loop < XMEM_NB_ROMS; Loop++)
	{
		FileContent += "Slot " + AnsiString(Loop) + " : ";
		if (mEmulatorP->IsBlankROM(mXMEMRomP + (Loop * ROM_SIZE), ROM_SIZE) == false)
		{
			if (Loop != 7)
			{
				FileContent += mEmulatorP->GetROMName(mXMEMRomP + (Loop * ROM_SIZE), ROM_SIZE);
			}
			else
			{
				FileContent += "Lower ROM";
			}
		}
		else
		{
			//FileContent += "Empty";
		}
		// End of line
		FileContent += "\r\n";
	}

	Application->MessageBox(((String)FileContent).c_str(), 
													_T("List of roms"),
													MB_OK);
	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::PanelButtonXMemRenameClick(TObject *Sender)
{
	AnsiString NewFileName = "X-Mem W29C040";

	// For all X-MEM Roms
	for (int Loop=0; Loop < XMEM_NB_ROMS; Loop++)
	{
		if (mEmulatorP->IsBlankROM(mXMEMRomP + (Loop * ROM_SIZE), ROM_SIZE) == false)
		{
			if (Loop != 7)
			{
				NewFileName += " " + AnsiString::IntToHex(Loop,2) + " ";
				NewFileName += mEmulatorP->GetROMShortName(mXMEMRomP + (Loop * ROM_SIZE), ROM_SIZE);
			}
		}

		// Filename length saturation
		if (NewFileName.Length() > 150)
			break;
	}

	// Add extension
	NewFileName += ExtractFileExt(mXMemFilename);

	OpenDialog->Title = "Rename X-Mem File...";
	OpenDialog->FileName = NewFileName;
	OpenDialog->InitialDir = mXMemDirectory;
	OpenDialog->Filter = XMEM_FILTER;
	OpenDialog->DefaultExt = XMEM_EXT;
	if (OpenDialog->Execute() == true)
	{
		// New filename does not exist ?
		if (FileExists(OpenDialog->FileName) == false)
		{
			if (RenameFile(mXMemDirectory + mXMemFilename, OpenDialog->FileName) == true)
			{
				mXMemDirectory = ExpandFileName(ExtractFilePath(OpenDialog->FileName));
				mXMemFilename = ExtractFileName(OpenDialog->FileName);
				// Update display
				LabelXMemFilename->Caption = mXMemFilename;
			}
		}
		else
		{
			Application->MessageBox(_T("File already exist using the automatic naming."),
															_T("Automatic renaming error."),
															MB_ICONEXCLAMATION | MB_OK);
		}
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::PageControlPeripheralsDrawTab(TCustomTabControl *Control,
          int TabIndex, const TRect &Rect, bool Active)
{
	TCanvas* Canvas = PageControlPeripherals->Canvas;

  if (Active == true)
  {
    Canvas->Font->Color = mSettingsP->ThemeText2Color;
  }

  // Get sheet corresponding to TabIndex
  int TabCount=0;
  TTabSheet* Sheet = NULL;
	for (int Loop=0; Loop < PageControlPeripherals->PageCount; Loop++)
  {
		if (PageControlPeripherals->Pages[Loop]->TabVisible == true)
    {
      if (TabCount == TabIndex)
      {
				Sheet = PageControlPeripherals->Pages[Loop];
        break;
      }

      TabCount++;
    }
  }

  // Draw tab
  Canvas->FillRect(Rect);
  AnsiString Text = Sheet->Caption;
  int TextWidth = Canvas->TextWidth(Text);
  int TextHeight = Canvas->TextHeight(Text);
  int TextPosX = (Rect.Width() - TextWidth) / 2;
  int TextPosY = (PageControlPeripherals->TabHeight - TextHeight) / 2;
  Canvas->TextOut(Rect.Left+TextPosX, Rect.Top+TextPosY, Text);

  NOT_USED(Control);
}
//---------------------------------------------------------------------------


void __fastcall TFormEmulatorSettings::PanelButtonXMassFileClick(TObject *Sender)
{
	OpenDialog->Title = "Select X-Mass File...";
	OpenDialog->FileName = mXMassFilename;
	OpenDialog->InitialDir = mXMassDirectory;
	OpenDialog->Filter = XMASS_FILTER;
	OpenDialog->DefaultExt = XMASS_EXT;
	OpenDialog->Options = OpenDialog->Options << ofFileMustExist;
	if (OpenDialog->Execute() == true)
	{
		mXMassDirectory = ExtractFilePath(OpenDialog->FileName);
		mXMassFilename = ExtractFileName(OpenDialog->FileName);

		// Update display
		LabelXMassFilename->Caption = mXMassFilename;
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TFormEmulatorSettings::PanelButtonXMassCreateClick(TObject *Sender)
{
	AnsiString XMassFilename = mXMassFilename;
	bool Create512M = RadioButtonXMASSCreate512Mo->Checked;
	if (Create512M == false)
	{
		OpenDialog->Title = "Create X-Mass 128M storage file";
	}
	else
	{
		OpenDialog->Title = "Create X-Mass 512M storage file";
	}
	OpenDialog->FileName = mXMassFilename;
	OpenDialog->InitialDir = mXMassDirectory;
	OpenDialog->Filter = XMASS_FILTER;
	OpenDialog->DefaultExt = XMASS_EXT;
	if (OpenDialog->Execute() == true)
	{
		bool Create = true;

		// XMass file already exists ?
		if (FileExists(OpenDialog->FileName) == true)
		{
			if (Application->MessageBox(_T("File already exists. Are you sure to loose all your data ?"),
																	_T("X-Mass storage file"),
																	MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2) == IDNO)
			{
				Create = false;
			}
		}

		if (Create == true)
		{
			TCursor OldCursor = Screen->Cursor;
			Screen->Cursor = crHourGlass;

			if (mEmulatorP->CreateIDEStorage(OpenDialog->FileName, Create512M) == false)
			{
				Application->MessageBox(_T("Error during creation."),
																_T("X-Mass storage file"),
																MB_ICONERROR | MB_OK);
			}
			else
			{
				// Use this file
				mXMassDirectory = ExtractFilePath(OpenDialog->FileName);
				mXMassFilename = ExtractFileName(OpenDialog->FileName);

				// Update display
				LabelXMassFilename->Caption = mXMassFilename;
			}

			Screen->Cursor = OldCursor;
		}
	}

	NOT_USED(Sender);
}
//---------------------------------------------------------------------------

