/***************************************************************************
 *   Copyright (C) 2005 by Mark Six                                        *
 *   marksix@xs4all.nl                                                     *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/


/* Revision History
 * V0.1: - Initial Version
 * V0.2:
 *     ADDED
 *		  - Improved debugging. Added Execution and Breakpoint icons in border.
 *        - Show more compiler messages.
 *        - Improved Syntax Highlighting (Now automatically installed).
 *		  - Improved the assembler. (Code is still a mess!)
 *        - Added icons.
 *        - Installation of the .desktop file is now in 'Development'
 * V0.3:
 *     ADDED
 *        - Export to HEX and MEM files
 * V0.4:
 *     ADDED
 *        - Expanded the debug toolbar.
 * V0.5:
 *     BUG FIX
 *        - Assembler: 'ORR sX, sY' assembled to 'ORR sX, kk' where kk was undefined
 *        - Simulator:  SUBCY sX, sY simulated wrongly (undefined behaviour)
 *                      SUBCY sX, kk simulated wrongly (undefined behaviour)
 *     IMPROVED
 *        - Change port ID per port and in serial window.
 *     ADDED
 *        - Save/Restore settings.
 *		  - Clear serial view popupmenu
 *
 * V0.6:
 *     ADDED
 *         - Debian packaging support by "Adrian Knoth"
 *         - Initial JTAG support
 *         - Initial Help
 *
 *     IDEAS (Oct 9, 2005)
 *			- Multiple picoblaze support
 *			- IO ports (and irq) can be changed from other software.
 *          - Download mem file with JTAG
 */


#include "kpicosim.h"

#include <tqlabel.h>

#include <tdemainwindow.h>
#include <tdelocale.h>

#include <tdemenubar.h>
#include <tqlayout.h>
#include <tqkeysequence.h>
#include <knuminput.h>
#include <tqnamespace.h>
#include <kportview.h>
#include <tqdockwindow.h>
#include <kstatusbar.h>
#include <kiconloader.h>
#include "kexportdialog.h"
#include "kjtagdialog.h"
#include <tdefiledialog.h>
#include <tdemessagebox.h>
#include <tqlayout.h>
#include <ksimpleconfig.h>
#include <khelpmenu.h>
#include <tdeaboutdata.h>

const char version[] = "0.6" ;

enum IDs {
	START_SIM_ID = 0,
	COMPILE_ID,
	RUN_ID,
	NEXT_ID,
	INTERRUPT_ID,
	RESET_ID,

	VIEW_SERIAL_ID,
	VIEW_SCRATCHPAD_ID
} ;


KPicoSim::KPicoSim() : TDEMainWindow( 0, "KPicoSim" )
{
//	set the shell's ui resource file
//	setXMLFile("kpicosimui.rc");

	m_splitter = new TQSplitter( this ) ;
	m_tabWidget = new TQTabWidget( m_splitter ) ;
	m_editor = new CodeEditor( m_tabWidget ) ;
	m_messages = new TDEListView( m_splitter, "messages" ) ;
	m_simulator = new KSimulator( TQT_TQOBJECT(this) ) ;
	m_processorView = new TDEProcessorView( this ) ;

	m_tabWidget->addTab( m_editor, "Source" ) ;
	addDockWindow( m_processorView, DockLeft ) ;

	m_splitter->setOrientation( Qt::Vertical ) ;
	setCentralWidget( m_splitter ) ;
	m_messages->setAllColumnsShowFocus( true ) ;
	m_messages->setFullWidth( true ) ;
	m_messages->resize( m_messages->width(), m_splitter->height() / 5 ) ;

	buildMenu() ;

	TDEToolBar *toolbar = new TDEToolBar( this ) ;
	addDockWindow( toolbar ) ;

	toolbar->insertButton( "document-new", -1, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(m_editor), TQT_SLOT( slotNewFile() ), true, "New" ) ;
	toolbar->insertButton( "document-open", -1, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(m_editor), TQT_SLOT( slotOpen() ), true, "Open" ) ;
	toolbar->insertButton( "document-save", -1, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(m_editor), TQT_SLOT( slotSave() ), true, "Save" ) ;
	toolbar->insertButton( "document-save-as", -1, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(m_editor), TQT_SLOT( slotSaveAs() ), true, "Save As" ) ;

	m_debugBar = new TDEToolBar( this ) ;
	addDockWindow( m_debugBar ) ;
	m_debugBar->insertButton( UserIcon( "rebuild" ), COMPILE_ID, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(this), TQT_SLOT( compile() ), true, "Compile" ) ;
	m_debugBar->insertButton( "system-run", START_SIM_ID, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(this), TQT_SLOT( startSim() ), true, "Start/Stop Debug" ) ;
	m_debugBar->insertSeparator() ;
	m_debugBar->insertButton( UserIcon( "continue" ), RUN_ID, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(this), TQT_SLOT( startStop() ), false, "Continue" ) ;

	m_debugBar->insertButton( UserIcon( "next" ), NEXT_ID, TQT_SIGNAL( clicked() ), m_simulator, TQT_SLOT( next() ), false, "Next" ) ;
	m_debugBar->insertButton( UserIcon( "interrupt" ), INTERRUPT_ID, TQT_SIGNAL( clicked() ), m_simulator, TQT_SLOT( interrupt() ), false, "Interrupt" ) ; 
	m_debugBar->insertButton( UserIcon( "reset" ), RESET_ID, TQT_SIGNAL( clicked() ), m_simulator, TQT_SLOT( reset() ), false, "Reset" ) ;

	connect( TQT_TQOBJECT(this), TQT_SIGNAL( run() ), m_simulator, TQT_SLOT( run() ) );
	connect( TQT_TQOBJECT(this), TQT_SIGNAL( stop()  ), m_simulator, TQT_SLOT( stop()  ) ) ;
	connect( m_simulator, TQT_SIGNAL( stepped( unsigned int ) ), TQT_TQOBJECT(this), TQT_SLOT( stepped( unsigned int ) ) ) ;
	connect( m_processorView, TQT_SIGNAL( processorRegsChanged() ), TQT_TQOBJECT(this), TQT_SLOT( updateProcessorRegs() ) ) ;
	connect( m_processorView, TQT_SIGNAL( processorFlagsChanged() ), TQT_TQOBJECT(this), TQT_SLOT( updateProcessorFlags() ) ) ;
	connect( m_messages, TQT_SIGNAL( clicked( TQListViewItem * ) ), TQT_TQOBJECT(this), TQT_SLOT( messageListClicked( TQListViewItem * ) ) ) ;

	m_messages->addColumn( "Line" ) ;
	m_messages->addColumn( "Description" ) ;
	m_messages->setSorting( -1, FALSE ) ;
	m_simulator->setMessageList( m_messages ) ;

	m_simulationMode = false ;
	m_scratchpadView = NULL ;
	m_serialView = NULL ;

	statusBar()->insertItem( TQString( "Mode: Edit" ), 0 ) ;
	statusBar()->insertItem( TQString( "Status: Stopped" ), 1 ) ;
	statusBar()->insertItem( TQString( "Instructions: 0" ), 2 ) ;

	m_templateFile = "" ;
	m_outputDir = "" ;
	m_entityName = "mpu_rom" ;


	openGUI() ;
}


void KPicoSim::buildMenu()
{
	TDEIconLoader * ldr = TDEGlobal::iconLoader() ;

	TDEPopupMenu * exportMenu = new TDEPopupMenu( this ) ;

	exportMenu->insertItem( "VHDL", TQT_TQOBJECT(this), TQT_SLOT( fileExportVHDL() ) ) ;
//	exportMenu->insertItem( "COE", TQT_TQOBJECT(this), TQT_SLOT( fileExportCOE() ) ) ;
	exportMenu->insertItem( "MEM", TQT_TQOBJECT(this), TQT_SLOT( fileExportMEM() ) ) ;
	exportMenu->insertItem( "HEX", TQT_TQOBJECT(this), TQT_SLOT( fileExportHEX() ) ) ;

	m_fileMenu = new TDEPopupMenu( this ) ;
	m_fileMenu->insertItem( ldr->loadIcon( "document-new", TDEIcon::Small ), "New", TQT_TQOBJECT(this), TQT_SLOT( slotFileNew() ) ) ;
	m_fileMenu->insertItem( ldr->loadIcon( "document-open", TDEIcon::Small ), "Open", TQT_TQOBJECT(m_editor), TQT_SLOT( slotOpen() ) ) ;
	m_fileMenu->insertSeparator() ;
	m_fileMenu->insertItem( ldr->loadIcon( "document-save", TDEIcon::Small ), "Save", TQT_TQOBJECT(m_editor), TQT_SLOT( slotSave() ), TQKeySequence( "CTRL+S" ) ) ;
	m_fileMenu->insertItem( ldr->loadIcon( "document-save-as", TDEIcon::Small ), "Save As...", TQT_TQOBJECT(m_editor), TQT_SLOT( slotSaveAs() ) ) ;
	m_fileMenu->insertSeparator() ;
	m_fileMenu->insertItem( ldr->loadIcon( "document-print", TDEIcon::Small ), "Print...", TQT_TQOBJECT(m_editor), TQT_SLOT( slotPrint() ), TQKeySequence( "CTRL+P" ) ) ;
	m_fileMenu->insertSeparator() ;
	m_fileMenu->insertItem( "Export", exportMenu ) ;
	m_fileMenu->insertSeparator() ;
	m_fileMenu->insertItem( ldr->loadIcon( "window-close", TDEIcon::Small ), "Quit", TQT_TQOBJECT(this), TQT_SLOT( slotClose() ) ) ;

	m_editMenu = new TDEPopupMenu( this ) ;
	m_editMenu->insertItem( ldr->loadIcon( "edit-undo", TDEIcon::Small ), "Undo", TQT_TQOBJECT(m_editor), TQT_SLOT( slotUndo() ),TQKeySequence( "CTRL+Z" ) ) ;
	m_editMenu->insertItem( ldr->loadIcon( "edit-redo", TDEIcon::Small ), "Redo", TQT_TQOBJECT(m_editor), TQT_SLOT( slotRedo() ),TQKeySequence( "CTRL+SHIFT+Z" ) ) ;
	m_editMenu->insertSeparator() ;
	m_editMenu->insertItem( "Select All", TQT_TQOBJECT(m_editor), TQT_SLOT( slotSelectAll() ),TQKeySequence( "CTRL+A" ) ) ;
	m_editMenu->insertSeparator() ;
	m_editMenu->insertItem( ldr->loadIcon( "edit-cut", TDEIcon::Small ), "Cut", TQT_TQOBJECT(m_editor), TQT_SLOT( slotCut() ),TQKeySequence( "CTRL+X" ) ) ;
	m_editMenu->insertItem( ldr->loadIcon( "edit-copy", TDEIcon::Small ), "Copy", TQT_TQOBJECT(m_editor), TQT_SLOT( slotCopy() ),TQKeySequence( "CTRL+C" ) ) ;
	m_editMenu->insertItem( ldr->loadIcon( "edit-paste", TDEIcon::Small ), "Paste", TQT_TQOBJECT(m_editor), TQT_SLOT( slotPaste() ),TQKeySequence( "CTRL+V" ) ) ;
	m_editMenu->insertSeparator() ;
	m_editMenu->insertItem( ldr->loadIcon( "edit-find", TDEIcon::Small ), "Find...", TQT_TQOBJECT(m_editor), TQT_SLOT( slotFind() ), TQKeySequence( "CTRL+F" ) ) ;
	m_editMenu->insertItem( "Find Next", TQT_TQOBJECT(m_editor), TQT_SLOT( slotFindNext() ), TQKeySequence( "F3" ) ) ;


	m_debugMenu = new TDEPopupMenu( this ) ;
	m_debugMenu->insertSeparator() ;
	m_debugMenu->insertItem( ldr->loadIcon( "rebuild", TDEIcon::Small ), "Compile", TQT_TQOBJECT(this), TQT_SLOT( compile() ), TQKeySequence( "SHIFT+F9" ) ) ;
	m_debugMenu->insertItem( ldr->loadIcon( "system-run", TDEIcon::Small ), "Start Debug", TQT_TQOBJECT(this), TQT_SLOT( startSim() ), TQKeySequence( "F9" ) , START_SIM_ID ) ;

	m_debugMenu->insertSeparator() ;
	m_debugMenu->insertItem( "Continue", TQT_TQOBJECT(this), TQT_SLOT( startStop() ), TQKeySequence( "F10" ) , RUN_ID ) ;
	m_debugMenu->insertItem( "Next", m_simulator, TQT_SLOT( next() ), TQKeySequence( "F5" ) , NEXT_ID ) ;
	m_debugMenu->insertItem( "Interrupt", m_simulator, TQT_SLOT( interrupt() ), TQKeySequence( "F4" ) , INTERRUPT_ID ) ;
	m_debugMenu->insertItem( "Reset", m_simulator, TQT_SLOT( reset() ), TQKeySequence( "F11" ) , RESET_ID ) ;

	m_debugMenu->insertSeparator() ;
	m_debugMenu->insertItem( "Toggle Breakpoint", TQT_TQOBJECT(m_editor), TQT_SLOT( slotToggleBreakpoint() ), TQKeySequence( "F8" ) ) ;

	m_settingsMenu = new TDEPopupMenu( this ) ;
	m_settingsMenu->insertItem( "Configure Editor...", TQT_TQOBJECT(m_editor), TQT_SLOT( slotShowConfig() ) ) ;

	m_peripheralMenu = new TDEPopupMenu( this ) ;
	m_peripheralMenu->insertItem( "I/O Port", TQT_TQOBJECT(this), TQT_SLOT( newIOPort() ) ) ;
	m_peripheralMenu->insertItem( "Scratchpad", TQT_TQOBJECT(this), TQT_SLOT( showScratchpad() ), 0, VIEW_SCRATCHPAD_ID ) ;
	m_peripheralMenu->insertItem( "Serial port", TQT_TQOBJECT(this), TQT_SLOT( showSerialPort() ), 0, VIEW_SERIAL_ID ) ;

	m_jtagMenu = new TDEPopupMenu( this ) ;
	m_jtagMenu->insertItem( "Download", TQT_TQOBJECT(this), TQT_SLOT( jtagDownload() ) ) ;

	TDEAboutData *aboutData = new TDEAboutData( 
		"kpicosim", 
		"kpicosim", 
		version, 
		"IDE for the picoblaze\n\nCopyright (c) 2005 Mark Six", 
		TDEAboutData::License_GPL,
		0,
		0,
		"http://www.xs4all.nl/~marksix",
		"m6@xs4all.nl"
	 ) ;
	aboutData->addAuthor( "Mark Six", "m6@xs4all.nl", "http://www.xs4all.nl/~marksix" ) ;

	KHelpMenu *helpMenu = new KHelpMenu( this, aboutData, false  ) ;
	TDEPopupMenu *help = helpMenu->menu() ;

	menuBar()->insertItem( "File", m_fileMenu ) ;
	menuBar()->insertItem( "Edit", m_editMenu ) ;
	menuBar()->insertItem( "Debug", m_debugMenu ) ;
	menuBar()->insertItem( "Peripheral", m_peripheralMenu ) ;
	menuBar()->insertItem( "JTAG", m_jtagMenu ) ;
	menuBar()->insertItem( "Settings", m_settingsMenu ) ;
	menuBar()->insertItem( "Help", help ) ;

	m_debugMenu->setItemEnabled( RUN_ID, false ) ;
	m_debugMenu->setItemEnabled( NEXT_ID, false ) ;
	m_debugMenu->setItemEnabled( INTERRUPT_ID, false ) ;
	m_debugMenu->setItemEnabled( RESET_ID, false ) ;

	m_peripheralMenu->setCheckable( true );
	m_peripheralMenu->setItemChecked( VIEW_SERIAL_ID, false ) ;
	m_peripheralMenu->setItemChecked( VIEW_SCRATCHPAD_ID, false ) ;


	menuBar()->show() ;
}

void KPicoSim::jtagDownload()
{
	/* JTAG is still in its infancy. This code works for me. I'm using the Xilinx Spartan-3
     * development board. If it works for you, great, if not too bad...
	 */

	KJTAGDialog dlg( this ) ;
	dlg.setFilename( m_bitfile ) ;
	dlg.exec() ;
	m_bitfile = dlg.getFilename() ;
}

void KPicoSim::fileExportCOE()
{
	KMessageBox::information( this, "This function is not supported yet", "Export COE" ) ;

//	if ( compile() ) {
		//m_simulator->exportCOE() ;
//	}
}

void KPicoSim::fileExportHEX()
{

	TQString filename = KFileDialog::getSaveFileName( TQString(), 
                                                     "*.hex|HEX files\n*|All files", 
		   										     this,
  												     "Export HEX" ) ;
	if ( filename != "" && compile() ) {
		m_simulator->exportHEX( filename.ascii(), FALSE ) ;
	}
}

void KPicoSim::fileExportMEM()
{

	TQString filename = KFileDialog::getSaveFileName( TQString(), 
                                                     "*.mem|MEM files\n*|All files", 
		   										     this,
  												     "Export MEM" ) ;
	if ( filename != "" && compile() ) {
		m_simulator->exportHEX( filename.ascii(), TRUE ) ;
	}
}

void KPicoSim::fileExportVHDL()
{
	KExportDialog dlg( this  ) ;
	
	dlg.setTemplateFile( m_templateFile ) ;
	dlg.setOutputDir( m_outputDir ) ;
	dlg.setEntityName( m_entityName ) ;
	dlg.modal() ;
	
	if ( dlg.isCanceled() ) 
		return ;
	
	m_templateFile = dlg.getTemplateFile() ;
	m_outputDir = dlg.getOutputDir() ;
	m_entityName = dlg.getEntityName() ;
		
	if ( compile() && m_simulator->exportVHDL( m_templateFile.ascii(), m_outputDir.ascii(), m_entityName.ascii() ) ) {
		appendMessage( "File '" + m_outputDir + "/" + m_entityName + ".vhd' exported" ) ;
		appendMessage( "Template file '" + m_templateFile + "' used" ) ;
		appendMessage( "***Export Success***" ) ;
	} else {
		appendMessage( "***Export failed***" ) ;
	}
}

void KPicoSim::slotFileNew()
{
	if ( m_editor->close() )
		m_editor->slotNewFile() ;
}

void KPicoSim::slotClose()
{
	close() ;
}

void KPicoSim::closeEvent( TQCloseEvent * e )
{
	if ( m_editor->close() )
		e->accept() ;


	// Save filename last opened
	// Save windows IO Ports, peripherals et al.
	closeGUI() ;
}

void KPicoSim::newIOPort()
{	
	KPortView * ioport = new KPortView( m_simulator->getCpu(), 0 ) ;			/* port id is 0 */
//	m_ioList.append( ioport ) ;
	addDockWindow( ioport, DockRight ) ;
//	connect( ioport, TQT_SIGNAL( closing( KPortView* ) ), TQT_TQOBJECT(this), TQT_SLOT( removeIOPort( KPortView* ) ) ) ;
}

void KPicoSim::showSerialPort()
{
	if ( m_serialView == NULL ) {
		m_serialView = new KSerialView( m_simulator->getCpu(), m_tabWidget ) ;
		m_tabWidget->addTab( m_serialView, "Serial" ) ;
		m_peripheralMenu->setItemChecked( VIEW_SERIAL_ID, true ) ;
	} else {
		m_peripheralMenu->setItemChecked( VIEW_SERIAL_ID, false ) ;
		delete m_serialView ;
		m_serialView = NULL ;
	}
}

void KPicoSim::showScratchpad()
{
	if ( m_scratchpadView == NULL ) {
		m_scratchpadView = new KScratchpadView( this ) ;
		updateScratchpadView() ;
		addDockWindow( m_scratchpadView, DockRight ) ;
		m_peripheralMenu->setItemChecked( VIEW_SCRATCHPAD_ID, true ) ;
	} else {
		m_peripheralMenu->setItemChecked( VIEW_SCRATCHPAD_ID, false ) ;
		delete m_scratchpadView ; 
		m_scratchpadView = NULL ;
	}
}

KPicoSim::~KPicoSim()
{
	// Delete dockwindows 
	// These are the IO ports, scratchpad and the processorview
	dockWindows().setAutoDelete( true ) ;
	dockWindows().clear() ;
	
	if ( m_serialView )	
		delete m_serialView ;
			
	delete m_simulator ;
	
	delete m_debugMenu ;
	delete m_editMenu ;
 	delete m_peripheralMenu ;
	delete m_fileMenu ;
	delete m_settingsMenu ;
}

void KPicoSim::startStop()
{
	if ( m_simulationMode ) {
		
		if ( !m_simulator->isRunning() ) {
			m_debugMenu->changeItem( RUN_ID, "Stop" ) ;
			m_editor->clearExecutionMarker() ;
			m_simulator->run() ;
			statusBar()->changeItem( TQString( "Status: Running" ), 1 ) ;
			m_debugBar->setButton( RUN_ID, true ) ;
		} else {
			m_simulator->stop() ;
			updateViews() ;
			m_debugMenu->changeItem( RUN_ID, "Continue" ) ;
			m_editor->setExecutionMarker( m_simulator->getNextSourceLine() ) ;
			statusBar()->changeItem( TQString( "Status: Stopped" ), 1 ) ;
			TQString str ;
			str.sprintf( "Instructions: %u", m_nrInstructions ) ;
			statusBar()->changeItem( str, 2 ) ;
			m_debugBar->setButton( RUN_ID, false ) ;
		}
	}
}

void KPicoSim::messageListClicked( TQListViewItem *item ) 
{
	if ( item ) {	
		bool ok ;
		int line = item->text(0).toInt( &ok, 10 ) ;
	
		if ( ok ) 
			m_editor->setCursor( line - 1 ) ;				// C-programmers do it from zero
	}
}

void KPicoSim::updateProcessorRegs()
{
	unsigned char regValues[ 16 ] ;
	m_processorView->getRegisterValues( regValues ) ;
	m_simulator->setRegisterValues( regValues ) ;
}

void KPicoSim::updateProcessorFlags()
{
	m_simulator->setFlags( m_processorView->getFlags() ) ;
}

void KPicoSim::updateViews() 
{
	unsigned char regValues[ 16 ] ;
	m_simulator->getRegisterValues( regValues ) ;
	m_processorView->setRegisterValues( regValues ) ;
	m_processorView->setFlags( m_simulator->getFlags() ) ;
	
	updateScratchpadView() ;

	TQString str ;
	str.sprintf( "Instructions: %u", m_nrInstructions ) ;
	statusBar()->changeItem( str, 2 ) ;
}

void KPicoSim::updateScratchpadView()
{
	if ( m_scratchpadView != NULL ) {
		unsigned char sp_ram[ 64 ] ;
		m_simulator->getScratchpad( sp_ram ) ;
		m_scratchpadView->setContent( sp_ram, sizeof( sp_ram ) ) ;
	}
}

void KPicoSim::stepped( unsigned int line )
{
	m_nrInstructions++ ;
	if ( m_simulator->isRunning() ) {
		if ( m_editor->isBreakpoint( line ) ) { ;
			startStop() ;
			m_editor->setExecutionMarker( line ) ;
		} else if ( (m_nrInstructions % 100 ) == 0 ) {
			updateViews() ;
		}
	} else {
		m_editor->setExecutionMarker( line ) ;
		updateViews() ;
	}
}

void KPicoSim::appendMessage( TQString str )
{
	TQListViewItem *item = new TQListViewItem( m_messages, m_messages->lastChild() ) ;
	item->setText( 0, "" ) ;
	item->setText( 1, str ) ;

}

bool KPicoSim::compile()
{
	m_simulator->clear() ;
	m_messages->clear() ;
	
	if ( !m_editor->save() ) 
		return FALSE;

	appendMessage( "File '" + m_editor->getFilename() + "' saved" ) ;
	m_simulator->setFilename( m_editor->getFilename().ascii() ) ;
		
	if ( m_simulator->compile() == TRUE ) {
		appendMessage( "***Compile Success*** " ) ;
		return TRUE ;
	} else {
		appendMessage( "***Compile Failed*** " ) ;
		return FALSE ;
	}
}


void KPicoSim::startSim()
{
	TDEIconLoader * ldr = TDEGlobal::iconLoader() ;

	if ( !m_simulationMode ) {
		if ( compile() ) {
			setCaption( m_editor->getFilename() + " [Debugging]" ) ;
			m_debugMenu->changeItem( START_SIM_ID, ldr->loadIcon( "process-stop", TDEIcon::Small ), "Stop Debug" ) ;
			m_debugBar->setButton( START_SIM_ID, true ) ;

			m_simulator->reset() ;
			m_nrInstructions = 0 ;
			m_simulationMode = TRUE ;
		}
	} else {
		if ( m_simulator->isRunning() )
			startStop() ;

		setCaption( m_editor->getFilename() ) ;
		m_debugMenu->changeItem( START_SIM_ID, ldr->loadIcon( "system-run", TDEIcon::Small ), "Start Debug" ) ;
		m_debugBar->setButton( START_SIM_ID, false ) ;
		m_editor->clearExecutionMarker() ;
		m_simulationMode = FALSE ;
	}

	if ( m_simulationMode ) {
		statusBar()->changeItem( TQString( "Mode: Debug" ), 0 ) ;
	} else {
		statusBar()->changeItem( TQString( "Mode: Edit" ), 0 ) ;
	}

	m_debugMenu->setItemEnabled( RUN_ID, m_simulationMode ) ;
	m_debugMenu->setItemEnabled( NEXT_ID, m_simulationMode ) ;
	m_debugMenu->setItemEnabled( INTERRUPT_ID, m_simulationMode ) ;
	m_debugMenu->setItemEnabled( RESET_ID, m_simulationMode ) ;

	m_debugBar->setItemEnabled( RUN_ID, m_simulationMode ) ;
	m_debugBar->setItemEnabled( NEXT_ID, m_simulationMode ) ;
	m_debugBar->setItemEnabled( INTERRUPT_ID, m_simulationMode ) ;
	m_debugBar->setItemEnabled( RESET_ID, m_simulationMode ) ;

}
/*
void KPicoSim::removeIOPort( KPortView* ioport )
{
	m_ioList.removeRef( ioport ) ;
}
*/
void KPicoSim::closeGUI()
{
	KSimpleConfig config( "kpicosim" ) ;

	config.setGroup( "Peripherals" ) ;
	
	config.writeEntry( "serial", m_serialView != NULL ) ;
	config.writeEntry( "scratchpad", m_scratchpadView != NULL ) ; 
	config.writeEntry( "filename", m_editor->getFilename() ) ;
	config.writeEntry( "bitfile", m_bitfile ) ;

/*
	config.writeEntry( "numIOPorts", m_ioList.count() ) ;
	for ( int i = 0 ; i < m_ioList.count() ; i++ ) {
		TQString group ;	
		group.sprintf( "IO Port %d", i ) ;
		m_ioList.at(i)->writeConfig( config, group ) ;
	}
*/
}

void KPicoSim::openGUI()
{
	KSimpleConfig config( "kpicosim" ) ;

	config.setGroup( "Peripherals" ) ;

	if ( config.readPropertyEntry( "serial", TQVariant::Bool ).toBool() )     
		showSerialPort() ;
	if ( config.readPropertyEntry( "scratchpad", TQVariant::Bool ).toBool() )	
		showScratchpad() ;
	m_editor->open( config.readEntry( "filename" ) ) ;
	m_bitfile = config.readEntry( "bitfile" ) ;

/*
	int nports = config.readPropertyEntry( "numIOPorts", TQVariant::Int ).toInt() ;

	for ( int i = 0 ; i < nports ; i++ ) {
		TQString group ;
		group.sprintf( "IO Port %d", i ) ;
		KPortView * ioport = new KPortView( m_simulator->getCpu(), 0 ) ;
		ioport->readConfig( config, group ) ;
		m_ioList.append( ioport ) ;
		addDockWindow( ioport, DockRight ) ;
		connect( ioport, TQT_SIGNAL( closing( KPortView* ) ), TQT_TQOBJECT(this), TQT_SLOT( removeIOPort( KPortView* ) ) ) ;
	}
*/
}

#include "kpicosim.moc"
