#include <guisan.hpp>
#include <guisan/sdl.hpp>
#include "SelectorEntry.hpp"
#include "StringListModel.h"

#include "sysdeps.h"
#include "options.h"
#include "memory.h"
#include "newcpu.h"
#include "gui_handling.h"

static gcn::Window* grpCPU;
static gcn::RadioButton* optCPU68000;
static gcn::RadioButton* optCPU68010;
static gcn::RadioButton* optCPU68020;
static gcn::RadioButton* optCPU68030;
static gcn::RadioButton* optCPU68040;
static gcn::CheckBox* chk24Bit;
static gcn::CheckBox* chkCPUCompatible;
static gcn::CheckBox* chkJIT;

static gcn::Window* grpFPU;
static gcn::RadioButton* optFPUnone;
static gcn::RadioButton* optFPU68881;
static gcn::RadioButton* optFPU68882;
static gcn::RadioButton* optFPUinternal;
static gcn::CheckBox* chkFPUstrict;
static gcn::CheckBox* chkFPUJIT;
static gcn::Window* grpCPUSpeed;
static gcn::RadioButton* opt7Mhz;
static gcn::RadioButton* opt14Mhz;
static gcn::RadioButton* opt25Mhz;
static gcn::RadioButton* optFastest;
static gcn::Label* lblCpuIdle;
static gcn::Slider* sldCpuIdle;
static gcn::Label* lblCpuIdleInfo;
static gcn::CheckBox* chkCPUCycleExact;

class CPUButtonActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		if (actionEvent.getSource() == optCPU68000)
		{
			changed_prefs.cpu_model = 68000;
			changed_prefs.fpu_model = 0;
			changed_prefs.address_space_24 = true;
			changed_prefs.z3fastmem[0].size = 0;
			changed_prefs.rtgboards[0].rtgmem_size = 0;
			changed_prefs.cachesize = 0;
			changed_prefs.compfpu = false;
		}
		else if (actionEvent.getSource() == optCPU68010)
		{
			changed_prefs.cpu_model = 68010;
			changed_prefs.fpu_model = 0;
			changed_prefs.address_space_24 = true;
			changed_prefs.z3fastmem[0].size = 0;
			changed_prefs.rtgboards[0].rtgmem_size = 0;
			changed_prefs.cachesize = 0;
			changed_prefs.compfpu = false;
		}
		else if (actionEvent.getSource() == optCPU68020)
		{
			changed_prefs.cpu_model = 68020;
			if (changed_prefs.fpu_model == 68040)
				changed_prefs.fpu_model = 68881;

			changed_prefs.cpu_cycle_exact = false;
			changed_prefs.blitter_cycle_exact = false;
			changed_prefs.cpu_memory_cycle_exact = false;
		}
		else if (actionEvent.getSource() == optCPU68030)
		{
			changed_prefs.cpu_model = 68030;
			if (changed_prefs.fpu_model == 68040)
				changed_prefs.fpu_model = 68881;
			changed_prefs.address_space_24 = false;
			changed_prefs.cpu_cycle_exact = false;
			changed_prefs.blitter_cycle_exact = false;
			changed_prefs.cpu_memory_cycle_exact = false;
		}
		else if (actionEvent.getSource() == optCPU68040)
		{
			changed_prefs.cpu_model = 68040;
			changed_prefs.fpu_model = 68040;
			changed_prefs.address_space_24 = false;
			changed_prefs.cpu_cycle_exact = false;
			changed_prefs.blitter_cycle_exact = false;
			changed_prefs.cpu_memory_cycle_exact = false;
		}
		RefreshPanelCPU();
		RefreshPanelRAM();
		RefreshPanelChipset();
	}
};

static CPUButtonActionListener* cpuButtonActionListener;

class FPUButtonActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		if (actionEvent.getSource() == optFPUnone)
		{
			changed_prefs.fpu_model = 0;
		}
		else if (actionEvent.getSource() == optFPU68881)
		{
			changed_prefs.fpu_model = 68881;
		}
		else if (actionEvent.getSource() == optFPU68882)
		{
			changed_prefs.fpu_model = 68882;
		}
		else if (actionEvent.getSource() == optFPUinternal)
		{
			changed_prefs.fpu_model = 68040;
		}
		RefreshPanelCPU();
		RefreshPanelRAM();
	}
};

static FPUButtonActionListener* fpuButtonActionListener;


class CPUSpeedButtonActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		if (actionEvent.getSource() == opt7Mhz)
			changed_prefs.m68k_speed = M68K_SPEED_7MHZ_CYCLES;
		else if (actionEvent.getSource() == opt14Mhz)
			changed_prefs.m68k_speed = M68K_SPEED_14MHZ_CYCLES;
		else if (actionEvent.getSource() == opt25Mhz)
			changed_prefs.m68k_speed = M68K_SPEED_25MHZ_CYCLES;
		else if (actionEvent.getSource() == optFastest)
			changed_prefs.m68k_speed = -1;
		else if (actionEvent.getSource() == chkCPUCycleExact) {
			if (chkCPUCycleExact->isSelected()) {
				changed_prefs.cpu_cycle_exact = true;
				changed_prefs.blitter_cycle_exact = true;
				changed_prefs.cpu_memory_cycle_exact = true;
				changed_prefs.cachesize = 0;
			}
			else {
				changed_prefs.cpu_cycle_exact = false;
				changed_prefs.blitter_cycle_exact = false;
				changed_prefs.cpu_memory_cycle_exact = false;
			}
			RefreshPanelChipset();
		}
	}
};

static CPUSpeedButtonActionListener* cpuSpeedButtonActionListener;


class CPU24BitActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		changed_prefs.address_space_24 = chk24Bit->isSelected();
		RefreshPanelCPU();
		RefreshPanelRAM();
	}
};

static CPU24BitActionListener* cpu24BitActionListener;

class CPUCompActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		if (chkCPUCompatible->isSelected())
		{
			changed_prefs.cpu_compatible = true;
			changed_prefs.cachesize = 0;
		}
		else
		{
			changed_prefs.cpu_compatible = false;
		}
		RefreshPanelCPU();
	}
};

static CPUCompActionListener* cpuCompActionListener;


class JITActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
#ifdef JIT
		if (actionEvent.getSource() == chkJIT)
		{
			if (chkJIT->isSelected())
			{
				changed_prefs.cpu_compatible = false;
				changed_prefs.cachesize = MAX_JIT_CACHE;
				changed_prefs.compfpu = true;
				changed_prefs.cpu_cycle_exact = false;
				changed_prefs.blitter_cycle_exact = false;
				changed_prefs.cpu_memory_cycle_exact = false;
				changed_prefs.address_space_24 = false;
			}
			else
			{
				changed_prefs.cachesize = 0;
				changed_prefs.compfpu = false;
			}
		}
		else if (actionEvent.getSource() == chkFPUJIT)
		{
			changed_prefs.compfpu = chkFPUJIT->isSelected();
		}
		RefreshPanelCPU();
		RefreshPanelChipset();
		RefreshPanelRAM();
#endif
	}
};

static JITActionListener* jitActionListener;

class FPUActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		if (actionEvent.getSource() == chkFPUstrict)
		{
			changed_prefs.fpu_strict = chkFPUstrict->isSelected();
		}
		RefreshPanelCPU();
	}
};

static FPUActionListener* fpuActionListener;

class CPUIdleSliderActionListener : public gcn::ActionListener
{
public:
	void action(const gcn::ActionEvent& actionEvent) override
	{
		if (actionEvent.getSource() == sldCpuIdle)
		{
			changed_prefs.cpu_idle = static_cast<int>(sldCpuIdle->getValue());
			if (changed_prefs.cpu_idle > 0)
				changed_prefs.cpu_idle = (12 - changed_prefs.cpu_idle) * 15;
		}
		RefreshPanelCPU();
	}
};

static CPUIdleSliderActionListener* cpuIdleActionListener;

void InitPanelCPU(const struct config_category& category)
{
	cpuButtonActionListener = new CPUButtonActionListener();
	cpu24BitActionListener = new CPU24BitActionListener();
	cpuCompActionListener = new CPUCompActionListener();
	jitActionListener = new JITActionListener();
	fpuActionListener = new FPUActionListener();
	cpuIdleActionListener = new CPUIdleSliderActionListener();

	optCPU68000 = new gcn::RadioButton("68000", "radiocpugroup");
	optCPU68000->setId("68000");
	optCPU68000->setBaseColor(gui_base_color);
	optCPU68000->setBackgroundColor(gui_textbox_background_color);
	optCPU68000->setForegroundColor(gui_foreground_color);
	optCPU68000->addActionListener(cpuButtonActionListener);
	optCPU68010 = new gcn::RadioButton("68010", "radiocpugroup");
	optCPU68010->setId("68010");
	optCPU68010->setBaseColor(gui_base_color);
	optCPU68010->setBackgroundColor(gui_textbox_background_color);
	optCPU68010->setForegroundColor(gui_foreground_color);
	optCPU68010->addActionListener(cpuButtonActionListener);
	optCPU68020 = new gcn::RadioButton("68020", "radiocpugroup");
	optCPU68020->setId("68020");
	optCPU68020->setBaseColor(gui_base_color);
	optCPU68020->setBackgroundColor(gui_textbox_background_color);
	optCPU68020->setForegroundColor(gui_foreground_color);
	optCPU68020->addActionListener(cpuButtonActionListener);
	optCPU68030 = new gcn::RadioButton("68030", "radiocpugroup");
	optCPU68030->setId("68030");
	optCPU68030->setBaseColor(gui_base_color);
	optCPU68030->setBackgroundColor(gui_textbox_background_color);
	optCPU68030->setForegroundColor(gui_foreground_color);
	optCPU68030->addActionListener(cpuButtonActionListener);
	optCPU68040 = new gcn::RadioButton("68040", "radiocpugroup");
	optCPU68040->setId("68040");
	optCPU68040->setBaseColor(gui_base_color);
	optCPU68040->setBackgroundColor(gui_textbox_background_color);
	optCPU68040->setForegroundColor(gui_foreground_color);
	optCPU68040->addActionListener(cpuButtonActionListener);

	chk24Bit = new gcn::CheckBox("24-bit addressing", true);
	chk24Bit->setId("CPU24Bit");
	chk24Bit->setBaseColor(gui_base_color);
	chk24Bit->setBackgroundColor(gui_textbox_background_color);
	chk24Bit->setForegroundColor(gui_foreground_color);
	chk24Bit->addActionListener(cpu24BitActionListener);

	chkCPUCompatible = new gcn::CheckBox("More compatible", true);
	chkCPUCompatible->setId("CPUComp");
	chkCPUCompatible->setBaseColor(gui_base_color);
	chkCPUCompatible->setBackgroundColor(gui_textbox_background_color);
	chkCPUCompatible->setForegroundColor(gui_foreground_color);
	chkCPUCompatible->addActionListener(cpuCompActionListener);

	chkJIT = new gcn::CheckBox("JIT", true);
	chkJIT->setId("JIT");
	chkJIT->setBaseColor(gui_base_color);
	chkJIT->setBackgroundColor(gui_textbox_background_color);
	chkJIT->setForegroundColor(gui_foreground_color);
	chkJIT->addActionListener(jitActionListener);

	grpCPU = new gcn::Window("CPU");
	grpCPU->setPosition(DISTANCE_BORDER, DISTANCE_BORDER);
	grpCPU->add(optCPU68000, 10, 10);
	grpCPU->add(optCPU68010, 10, 40);
	grpCPU->add(optCPU68020, 10, 70);
	grpCPU->add(optCPU68030, 10, 100);
	grpCPU->add(optCPU68040, 10, 130);
	grpCPU->add(chk24Bit, 10, 170);
	grpCPU->add(chkCPUCompatible, 10, 200);
	grpCPU->add(chkJIT, 10, 230);
	grpCPU->setMovable(false);
	grpCPU->setSize(chk24Bit->getWidth() + 20, 285);
	grpCPU->setTitleBarHeight(TITLEBAR_HEIGHT);
	grpCPU->setBaseColor(gui_base_color);
	grpCPU->setForegroundColor(gui_foreground_color);
	category.panel->add(grpCPU);

	fpuButtonActionListener = new FPUButtonActionListener();

	optFPUnone = new gcn::RadioButton("None", "radiofpugroup");
	optFPUnone->setId("FPUnone");
	optFPUnone->setBaseColor(gui_base_color);
	optFPUnone->setBackgroundColor(gui_textbox_background_color);
	optFPUnone->setForegroundColor(gui_foreground_color);
	optFPUnone->addActionListener(fpuButtonActionListener);

	optFPU68881 = new gcn::RadioButton("68881", "radiofpugroup");
	optFPU68881->setId("68881");
	optFPU68881->setBaseColor(gui_base_color);
	optFPU68881->setBackgroundColor(gui_textbox_background_color);
	optFPU68881->setForegroundColor(gui_foreground_color);
	optFPU68881->addActionListener(fpuButtonActionListener);

	optFPU68882 = new gcn::RadioButton("68882", "radiofpugroup");
	optFPU68882->setId("68882");
	optFPU68882->setBaseColor(gui_base_color);
	optFPU68882->setBackgroundColor(gui_textbox_background_color);
	optFPU68882->setForegroundColor(gui_foreground_color);
	optFPU68882->addActionListener(fpuButtonActionListener);

	optFPUinternal = new gcn::RadioButton("CPU internal", "radiofpugroup");
	optFPUinternal->setId("CPU internal");
	optFPUinternal->setBaseColor(gui_base_color);
	optFPUinternal->setBackgroundColor(gui_textbox_background_color);
	optFPUinternal->setForegroundColor(gui_foreground_color);
	optFPUinternal->addActionListener(fpuButtonActionListener);

	chkFPUstrict = new gcn::CheckBox("More compatible", true);
	chkFPUstrict->setId("FPUstrict");
	chkFPUstrict->setBaseColor(gui_base_color);
	chkFPUstrict->setBackgroundColor(gui_textbox_background_color);
	chkFPUstrict->setForegroundColor(gui_foreground_color);
	chkFPUstrict->addActionListener(fpuActionListener);

	chkFPUJIT = new gcn::CheckBox("FPU JIT", true);
	chkFPUJIT->setId("FPUJIT");
	chkFPUJIT->setBaseColor(gui_base_color);
	chkFPUJIT->setBackgroundColor(gui_textbox_background_color);
	chkFPUJIT->setForegroundColor(gui_foreground_color);
	chkFPUJIT->addActionListener(jitActionListener);

	grpFPU = new gcn::Window("FPU");
	grpFPU->setPosition(DISTANCE_BORDER + grpCPU->getWidth() + DISTANCE_NEXT_X, DISTANCE_BORDER);
	grpFPU->add(optFPUnone, 10, 10);
	grpFPU->add(optFPU68881, 10, 40);
	grpFPU->add(optFPU68882, 10, 70);
	grpFPU->add(optFPUinternal, 10, 100);
	grpFPU->add(chkFPUstrict, 10, 140);
	grpFPU->add(chkFPUJIT, 10, 170);
	grpFPU->setMovable(false);
	grpFPU->setSize(175, 285);
	grpFPU->setTitleBarHeight(TITLEBAR_HEIGHT);
	grpFPU->setBaseColor(gui_base_color);
	grpFPU->setForegroundColor(gui_foreground_color);
	category.panel->add(grpFPU);

	cpuSpeedButtonActionListener = new CPUSpeedButtonActionListener();

	opt7Mhz = new gcn::RadioButton("7 Mhz", "radiocpuspeedgroup");
	opt7Mhz->setId("7 Mhz");
	opt7Mhz->setBaseColor(gui_base_color);
	opt7Mhz->setBackgroundColor(gui_textbox_background_color);
	opt7Mhz->setForegroundColor(gui_foreground_color);
	opt7Mhz->addActionListener(cpuSpeedButtonActionListener);

	opt14Mhz = new gcn::RadioButton("14 Mhz", "radiocpuspeedgroup");
	opt14Mhz->setId("14 Mhz");
	opt14Mhz->setBaseColor(gui_base_color);
	opt14Mhz->setBackgroundColor(gui_textbox_background_color);
	opt14Mhz->setForegroundColor(gui_foreground_color);
	opt14Mhz->addActionListener(cpuSpeedButtonActionListener);

	opt25Mhz = new gcn::RadioButton("25 Mhz", "radiocpuspeedgroup");
	opt25Mhz->setId("25 Mhz");
	opt25Mhz->setBaseColor(gui_base_color);
	opt25Mhz->setBackgroundColor(gui_textbox_background_color);
	opt25Mhz->setForegroundColor(gui_foreground_color);
	opt25Mhz->addActionListener(cpuSpeedButtonActionListener);

	optFastest = new gcn::RadioButton("Fastest", "radiocpuspeedgroup");
	optFastest->setId("Fastest");
	optFastest->setBaseColor(gui_base_color);
	optFastest->setBackgroundColor(gui_textbox_background_color);
	optFastest->setForegroundColor(gui_foreground_color);
	optFastest->addActionListener(cpuSpeedButtonActionListener);

	chkCPUCycleExact = new gcn::CheckBox("Cycle exact", true);
	chkCPUCycleExact->setId("chkCPUCycleExact");
	chkCPUCycleExact->setBaseColor(gui_base_color);
	chkCPUCycleExact->setBackgroundColor(gui_textbox_background_color);
	chkCPUCycleExact->setForegroundColor(gui_foreground_color);
	chkCPUCycleExact->addActionListener(cpuSpeedButtonActionListener);
	
	lblCpuIdle = new gcn::Label("CPU Idle");
	sldCpuIdle = new gcn::Slider(0, 10);
	sldCpuIdle->setSize(90, SLIDER_HEIGHT);
	sldCpuIdle->setBaseColor(gui_base_color);
	sldCpuIdle->setBackgroundColor(gui_textbox_background_color);
	sldCpuIdle->setForegroundColor(gui_foreground_color);
	sldCpuIdle->setMarkerLength(20);
	sldCpuIdle->setStepLength(1);
	sldCpuIdle->setId("sldCpuIdle");
	sldCpuIdle->addActionListener(cpuIdleActionListener);
	lblCpuIdleInfo = new gcn::Label("000");

	grpCPUSpeed = new gcn::Window("CPU Speed");
	grpCPUSpeed->setPosition(grpFPU->getX() + grpFPU->getWidth() + DISTANCE_NEXT_X, DISTANCE_BORDER);
	grpCPUSpeed->add(opt7Mhz, 10, 10);
	grpCPUSpeed->add(opt14Mhz, 10, 40);
	grpCPUSpeed->add(opt25Mhz, 10, 70);
	grpCPUSpeed->add(optFastest, 10, 100);
	grpCPUSpeed->add(chkCPUCycleExact, 10, 160);
	grpCPUSpeed->add(lblCpuIdle, 10, 190);
	grpCPUSpeed->add(sldCpuIdle, lblCpuIdle->getX() + lblCpuIdle->getWidth() + DISTANCE_NEXT_X/2, 190);
	grpCPUSpeed->add(lblCpuIdleInfo, sldCpuIdle->getX() + sldCpuIdle->getWidth() + DISTANCE_NEXT_X / 2, 190);
	grpCPUSpeed->setMovable(false);
	grpCPUSpeed->setSize(190, 285);
	grpCPUSpeed->setTitleBarHeight(TITLEBAR_HEIGHT);
	grpCPUSpeed->setBaseColor(gui_base_color);
	grpCPUSpeed->setForegroundColor(gui_foreground_color);

	category.panel->add(grpCPUSpeed);

	RefreshPanelCPU();
}

void ExitPanelCPU()
{
	delete optCPU68000;
	delete optCPU68010;
	delete optCPU68020;
	delete optCPU68030;
	delete optCPU68040;
	delete chk24Bit;
	delete chkCPUCompatible;
	delete chkJIT;
	delete grpCPU;
	delete cpuButtonActionListener;
	delete cpu24BitActionListener;
	delete cpuCompActionListener;
	delete jitActionListener;

	delete optFPUnone;
	delete optFPU68881;
	delete optFPU68882;
	delete optFPUinternal;
	delete chkFPUstrict;
	delete chkFPUJIT;
	delete grpFPU;
	delete fpuButtonActionListener;
	delete fpuActionListener;

	delete opt7Mhz;
	delete opt14Mhz;
	delete opt25Mhz;
	delete optFastest;
	delete lblCpuIdle;
	delete sldCpuIdle;
	delete lblCpuIdleInfo;
	delete chkCPUCycleExact;
	delete cpuIdleActionListener;
	
	delete grpCPUSpeed;
	delete cpuSpeedButtonActionListener;
}

void RefreshPanelCPU()
{
	if (changed_prefs.cpu_model == 68000)
		optCPU68000->setSelected(true);
	else if (changed_prefs.cpu_model == 68010)
		optCPU68010->setSelected(true);
	else if (changed_prefs.cpu_model == 68020)
		optCPU68020->setSelected(true);
	else if (changed_prefs.cpu_model == 68030)
		optCPU68030->setSelected(true);
	else if (changed_prefs.cpu_model == 68040)
		optCPU68040->setSelected(true);

	chk24Bit->setSelected(changed_prefs.address_space_24);
	chk24Bit->setEnabled(changed_prefs.cpu_model == 68020 && changed_prefs.cachesize == 0);
	
	chkCPUCompatible->setSelected(changed_prefs.cpu_compatible > 0);
	chkCPUCompatible->setEnabled(changed_prefs.cachesize == 0);
	
	chkCPUCycleExact->setSelected(changed_prefs.cpu_cycle_exact > 0);
	chkCPUCycleExact->setEnabled(changed_prefs.cpu_model <= 68010);

#ifdef JIT
	chkJIT->setEnabled(changed_prefs.cpu_model >= 68020);
	chkJIT->setSelected(changed_prefs.cachesize > 0);
#else
	chkJIT->setEnabled(false);
	chkJIT->setSelected(false);
#endif

	switch (changed_prefs.fpu_model)
	{
	case 68881:
		optFPU68881->setSelected(true);
		break;
	case 68882:
		optFPU68882->setSelected(true);
		break;
	case 68040:
		optFPUinternal->setSelected(true);
		break;
	default:
		optFPUnone->setSelected(true);
		break;
	}
	optFPU68881->setEnabled(changed_prefs.cpu_model >= 68020 && changed_prefs.cpu_model < 68040);
	optFPU68882->setEnabled(changed_prefs.cpu_model >= 68020 && changed_prefs.cpu_model < 68040);
	optFPUinternal->setEnabled(changed_prefs.cpu_model == 68040);

	chkFPUstrict->setSelected(changed_prefs.fpu_strict);

#ifdef USE_JIT_FPU
	chkFPUJIT->setEnabled(changed_prefs.cachesize > 0);
	chkFPUJIT->setSelected(changed_prefs.cachesize > 0 && changed_prefs.compfpu);
#else
	chkFPUJIT->setSelected(false);
	chkFPUJIT->setEnabled(false);
#endif

#ifndef JIT
	chkFPUJIT->setSelected(false);
	chkFPUJIT->setEnabled(false);
#endif

	if (changed_prefs.m68k_speed == M68K_SPEED_7MHZ_CYCLES)
		opt7Mhz->setSelected(true);
	else if (changed_prefs.m68k_speed == M68K_SPEED_14MHZ_CYCLES)
		opt14Mhz->setSelected(true);
	else if (changed_prefs.m68k_speed == M68K_SPEED_25MHZ_CYCLES)
		opt25Mhz->setSelected(true);
	else if (changed_prefs.m68k_speed == -1)
		optFastest->setSelected(true);

	sldCpuIdle->setValue(changed_prefs.cpu_idle == 0 ? 0 : 12 - changed_prefs.cpu_idle / 15);
	const auto cpu_idle = to_string((changed_prefs.cpu_idle == 0 ? 0 : 12 - changed_prefs.cpu_idle / 15) * 10);
	lblCpuIdleInfo->setCaption(cpu_idle);
}

bool HelpPanelCPU(std::vector<std::string>& helptext)
{
	helptext.clear();
	helptext.emplace_back("Select the required Amiga CPU (68000 - 68040). If you select 68020, you can choose");
	helptext.emplace_back("between 24-bit (68EC020) or 32-bit (68020) addressing.");
	helptext.emplace_back(" ");
	helptext.emplace_back("The option \"More compatible\" is only available if 68000 or 68010 is selected, and");
	helptext.emplace_back("emulates simple prefetch of the 68000. This may improve compatibility in certain");
	helptext.emplace_back("situations, but is not normally required for most games and demos.");
	helptext.emplace_back(" ");
	helptext.emplace_back("JIT/JIT FPU enables the Just-in-time compiler. This may break compatibility in some games.");
	helptext.emplace_back(" ");
	helptext.emplace_back("The available FPU models depend on the selected CPU type. The option \"More compatible\"");
	helptext.emplace_back("activates a more accurate rounding method and compare of two floats.");
	helptext.emplace_back(" ");
	helptext.emplace_back("With \"CPU Speed\" you can choose the clock rate of the emulated Amiga. Use 7MHz for A500,");
	helptext.emplace_back("or 14MHz for A1200 speed. Fastest Possible will only give the minimum time to the Chipset,");
	helptext.emplace_back("and maximum time as possible for the CPU, which may result in dropped frames.\"Cycle exact\"");
	helptext.emplace_back("emulates 68000/chipset cycles accurately, is very slow and not required in most situations.");
	helptext.emplace_back(" ");
	helptext.emplace_back("You can use the CPU Idle slider to set how much the CPU emulation should sleep when idle.");
	helptext.emplace_back("This is useful on some small devices, to help keep the system temperature down.");
	helptext.emplace_back(" ");
	helptext.emplace_back("In current version, you will not see a difference in the performance for 68020, 68030 and");
	helptext.emplace_back("68040 CPUs. The current CPU cycles for all the opcodes are based on 68020. The different");
	helptext.emplace_back("cycles for 68030 and 68040 may come in a later version.");
	return true;
}
