/*
Copyright (c) 1998 Richard Lawrence

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// CHardwareDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Atari800Win.h"
#include "CHardwareDlg.h"
#include "CWarnDlg.h"
#include "winatari.h"
#include "crc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define MACHINE_TYPES	7

extern "C" 
{
#include "registry.h"
#include "rt-config.h"
extern int	default_system;
extern ULONG	ulAtariState;
extern int enable_rom_patches;
extern int test_val;
extern int global_artif_mode;
extern ULONG ulMiscStates;
extern void art_main_init(int init_flag, int mode);
extern void RestoreSIO( void );
extern void SetSIOEsc( void );
extern void Atari_ReInit( void );
extern ULONG	ulDontShowFlags;
extern unsigned long CheckFile( char *fn, int *result );
extern int Ram256;
}

static char BASED_CODE szFilter[] = "ROM Images (*.rom)|*.rom|All Files (*.*)|*.*||";
static unsigned long ulFileCRC[MACHINE_TYPES] = { 0L, 3252116993L, 3764596111L, 3764596111L, 3764596111L, 3764596111L, 3182898204L };
static unsigned int unWarnBits[MACHINE_TYPES] = { DONT_SHOW_OSA_WARN, DONT_SHOW_OSB_WARN, DONT_SHOW_XL_WARN, DONT_SHOW_XL_WARN, DONT_SHOW_XL_WARN, DONT_SHOW_XL_WARN, DONT_SHOW_5200_WARN };
static char *pszRomNames[MACHINE_TYPES] = { atari_osa_filename, atari_osb_filename, atari_xlxe_filename, atari_xlxe_filename, atari_xlxe_filename, atari_xlxe_filename, atari_5200_filename };
static char szNewRomNames[MACHINE_TYPES][MAX_PATH];
static int	nNewSystem, nNewArtif, nNewRomPatch, nOrigSystem;
/////////////////////////////////////////////////////////////////////////////
// CHardwareDlg dialog


CHardwareDlg::CHardwareDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHardwareDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHardwareDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CHardwareDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHardwareDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHardwareDlg, CDialog)
	//{{AFX_MSG_MAP(CHardwareDlg)
	ON_NOTIFY(UDN_DELTAPOS, IDC_REFRESH_SPIN, OnDeltaposRefreshSpin)
	ON_BN_CLICKED(IDC_NTSC, OnNtsc)
	ON_BN_CLICKED(IDC_PAL, OnPal)
	ON_EN_KILLFOCUS(IDC_REFRESH_RATE, OnKillfocusRefreshRate)
	ON_BN_CLICKED(IDC_ROMFILE, OnRomfile)
	ON_EN_KILLFOCUS(IDC_ROM_EDIT, OnKillfocusRomEdit)
	ON_CBN_SELCHANGE(IDC_MACHINE_SELECTOR, OnSelchangeMachineSelector)
	ON_CBN_SELCHANGE(IDC_ARTIFACT_MODE, OnSelchangeArtifactMode)
	ON_BN_CLICKED(IDC_ENABLE_ROM, OnEnableRom)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHardwareDlg message handlers

void CHardwareDlg::SetDisplay()
{
	char	cDigits[64];
	CComboBox	*pCombo = NULL;

	pCombo = (CComboBox *)GetDlgItem( IDC_ARTIFACT_MODE );
	ASSERT( pCombo );
	pCombo->SetCurSel( nNewArtif );

	if( nNewSystem >= 0 && nNewSystem <= MACHINE_TYPES  )
	{
		pCombo = (CComboBox *)GetDlgItem( IDC_MACHINE_SELECTOR );
		ASSERT( pCombo );
		pCombo->SetCurSel( nNewSystem - 1 );
		SetDlgItemText( IDC_ROM_EDIT, szNewRomNames[ nNewSystem - 1 ] );
	}
	else
		SetDlgItemText( IDC_ROM_EDIT, "Bad machine type, please reselect" );

	if( default_tv_mode == 1 )
		CheckRadioButton( IDC_NTSC, IDC_PAL, IDC_PAL );
	else
		CheckRadioButton( IDC_NTSC, IDC_PAL, IDC_NTSC );

	ntemp_tv_mode = default_tv_mode;
	ntemp_refresh_rate = refresh_rate;

	itoa( ntemp_refresh_rate, cDigits, 10 );
	SetDlgItemText( IDC_REFRESH_RATE, cDigits );

	if( ulMiscStates & ATARI_FULL_SPEED )
	{
		CButton	*cbSpeed = (CButton *)GetDlgItem( IDC_FULL_SPEED );
		ASSERT( cbSpeed );
		cbSpeed->SetCheck( 1 );
	}

	CButton *cb = (CButton *)GetDlgItem( IDC_ENABLE_ROM );
	ASSERT( cb );
	if( nNewRomPatch )
	{
		cb->SetCheck( 1 );

		if( enable_sio_patch )
		{
			cb = (CButton *)GetDlgItem( IDC_ENABLE_SIO );
			ASSERT( cb );
			cb->SetCheck( 1 );
		}
	}
	else	/* ROM patch == FALSE automatically disables SIO_PATCH */
	{
		cb->SetCheck( 0 );
		cb = (CButton *)GetDlgItem( IDC_ENABLE_SIO );
		ASSERT( cb );
		cb->SetCheck( 0 );
	}

	if( enable_c000_ram )
	{
		CButton *cbC000 = (CButton *)GetDlgItem( IDC_C000_RAM );
		ASSERT( cbC000 );
		cbC000->SetCheck( 1 );
	}
}

BOOL CHardwareDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	int		i;

	switch (default_system) {
		case 1:
			nNewSystem = 1;		// OS-A
			break;
		case 2:
			nNewSystem = 2;		// OS-B
			break;
		case 3:
			nNewSystem = 3;		// 800 XL
			break;
		case 4:
			nNewSystem = 4;		// 130 XE
			break;
		case 5:
			if( Ram256 == 2 )
				nNewSystem = 5;	// 320 XE Compy
			else
				nNewSystem = 6;	// 320 XE Rambo
			break;
		case 6:
			nNewSystem = 7;		// 5200
			break;
		default:
			nNewSystem = 2;		// OS-B
			break;
	}

	nOrigSystem = nNewSystem;

	nNewArtif = global_artif_mode;

	nNewRomPatch = enable_rom_patches;

	if( default_tv_mode < 1 || default_tv_mode > 2 )
		default_tv_mode = 1;

	for( i = 0; i < MACHINE_TYPES; i++ )
		strcpy( szNewRomNames[i], pszRomNames[i] );

	SetDisplay();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

int CHardwareDlg::SetRomImage( int idnum, unsigned long expectedCrc, unsigned long dontshowbit, char *warningtext )
{
	CString	name;
	CFileDialog	cfRomImage( TRUE, NULL, NULL, OFN_EXPLORER | OFN_FILEMUSTEXIST, szFilter, this );
	char	szDlgBuf[ MAX_PATH ];
	int	nBtn;

	cfRomImage.m_ofn.lpstrTitle = "Select the ROM for this machine type";
	nBtn = cfRomImage.DoModal();
	if( nBtn == IDOK )
	{
		name = cfRomImage.GetPathName();
		GetDlgItemText( idnum, szDlgBuf, MAX_PATH );
		SetDlgItemText( idnum, name.GetBuffer(0) );
		nBtn = OnKillfocusRomEdit();
		if( nBtn != IDOK )
			SetDlgItemText( idnum, szDlgBuf );
	}
	return nBtn;
}

void CHardwareDlg::OnSelchangeArtifactMode() 
{
	CComboBox	*pCombo = NULL;
		
	pCombo = (CComboBox *)GetDlgItem( IDC_ARTIFACT_MODE );
	ASSERT( pCombo );
	
	nNewArtif = pCombo->GetCurSel();
}

void CHardwareDlg::OnSelchangeMachineSelector() 
{
	CComboBox	*pCombo = NULL;
		
	pCombo = (CComboBox *)GetDlgItem( IDC_MACHINE_SELECTOR );
	ASSERT( pCombo );

	nNewSystem = pCombo->GetCurSel( ) + 1;
	SetDisplay();
}

int CHardwareDlg::OnKillfocusRomEdit() 
{
	char	szDlgBuf[ MAX_PATH ];
	int		nresult, nBtn = IDOK;
	unsigned long	ulCRC;

	GetDlgItemText( IDC_ROM_EDIT, szDlgBuf, MAX_PATH );
	ulCRC = CheckFile( szDlgBuf, &nresult);

	if( ulCRC && !nresult && (ulCRC != ulFileCRC[ nNewSystem - 1] ) && !(ulDontShowFlags & unWarnBits[nNewSystem - 1] ) )
	{
		CWarnDlg	Warning;
		char	message[LOADSTRING_STRING_SIZE];		
		LoadString( NULL, IDS_WARNING_ROM_CORRUPT, message, LOADSTRING_STRING_SIZE );
		Warning.csWarnText = message;
		Warning.iWarnBit = unWarnBits[nNewSystem - 1];
		nBtn = Warning.DoModal();
	}

	if( nBtn == IDOK )
	{
		strcpy( szNewRomNames[ nNewSystem - 1], szDlgBuf );
		if( nNewSystem > 2 && nNewSystem < MACHINE_TYPES - 1  )
		{
			strcpy( szNewRomNames[2], szDlgBuf );
			strcpy( szNewRomNames[3], szDlgBuf );
			strcpy( szNewRomNames[4], szDlgBuf );
			strcpy( szNewRomNames[5], szDlgBuf );
		}
	}

	SetDisplay();
	return nBtn;
}

void CHardwareDlg::OnRomfile() 
{
	char	message[LOADSTRING_STRING_SIZE];		

	ASSERT( nNewSystem >= 0 && nNewSystem <= MACHINE_TYPES  );

	LoadString( NULL, IDS_WARNING_ROM_CORRUPT, message, LOADSTRING_STRING_SIZE );
	SetRomImage( IDC_ROM_EDIT, ulFileCRC[ nNewSystem - 1 ], unWarnBits[ nNewSystem -1 ], message );
}

void CHardwareDlg::OnDeltaposRefreshSpin(NMHDR* pNMHDR, LRESULT* pResult) 
{
	char	cDigits[64];
	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;

	ntemp_refresh_rate -= pNMUpDown->iDelta;
	if( ntemp_refresh_rate < 1 )
		ntemp_refresh_rate = 1;
	if( ntemp_refresh_rate > 99 )
		ntemp_refresh_rate = 99;

	itoa( ntemp_refresh_rate, cDigits, 10 );
	SetDlgItemText( IDC_REFRESH_RATE, cDigits );

	test_val = 0;
	*pResult = 0;
}

void CHardwareDlg::OnKillfocusRefreshRate() 
{
	char	cDigits[64];
	int		iTemp;

	GetDlgItemText( IDC_REFRESH_RATE, cDigits, 64 );
	iTemp = atoi( cDigits );

	if( iTemp < 1 || iTemp > 99 )
	{
		itoa( ntemp_refresh_rate, cDigits, 10 );
		SetDlgItemText( IDC_REFRESH_RATE, cDigits );
	}
	else
		ntemp_refresh_rate = iTemp;
}

void CHardwareDlg::OnNtsc() 
{
	ntemp_tv_mode = 2;
}

void CHardwareDlg::OnPal() 
{
	ntemp_tv_mode = 1;
}

void CHardwareDlg::OnEnableRom() 
{
	CButton *cb = (CButton *)GetDlgItem( IDC_ENABLE_ROM );

	nNewRomPatch = cb->GetCheck();
	SetDisplay();
}

void CHardwareDlg::OnOK() 
{
	int		i;
	BOOL	bReboot = FALSE, bSaveOS = FALSE;
	CButton	*cbButton = (CButton *)GetDlgItem( IDC_FULL_SPEED );
	ULONG	ulTempStates = ulMiscStates;

	ASSERT( cbButton );
	if( nNewArtif != global_artif_mode )
	{
		global_artif_mode = nNewArtif;
		art_main_init( 0, global_artif_mode );
		//bReboot = TRUE;
		WriteRegDWORD( NULL, REG_ARTIF_MODE, global_artif_mode );
	}

	if( ulAtariState & ATARI_LOAD_FAILED )
		bReboot = TRUE;

	if( cbButton->GetCheck() )
		ulMiscStates |= ATARI_FULL_SPEED;
	else
		ulMiscStates &= ~ATARI_FULL_SPEED;

	cbButton = (CButton *)GetDlgItem( IDC_C000_RAM );
	ASSERT( cbButton );
	if( cbButton->GetCheck()!=enable_c000_ram )
	{
		enable_c000_ram = cbButton->GetCheck();
		bReboot = TRUE;
		WriteRegDWORD( NULL, REG_ENABLE_C000_RAM, enable_c000_ram );
	}

	cbButton = (CButton *)GetDlgItem( IDC_ENABLE_SIO );
	ASSERT( cbButton );
	if( cbButton->GetCheck()!=enable_sio_patch )
	{
		enable_sio_patch = cbButton->GetCheck();
		if( enable_sio_patch )
			SetSIOEsc();
		else
			RestoreSIO();
		WriteRegDWORD( NULL, REG_ENABLE_SIO_PATCH, enable_sio_patch );
	}

	if( nNewRomPatch != enable_rom_patches )
	{
		bReboot = TRUE;
		enable_rom_patches = nNewRomPatch;
	}

	for( i = 0 ; i < MACHINE_TYPES; i ++ )
	{
		if( strcmp( pszRomNames[i], szNewRomNames[i] ) )
			bSaveOS = TRUE;
		strcpy( pszRomNames[i], szNewRomNames[i] );
	}

	if( bSaveOS )
	{
		WriteRegString( NULL, REG_OSA_ROM, atari_osa_filename );
		WriteRegString( NULL, REG_OSB_ROM, atari_osb_filename );
		WriteRegString( NULL, REG_XLXE_ROM, atari_xlxe_filename );
		WriteRegString( NULL, REG_5200_ROM, atari_5200_filename );
	}

	if( nNewSystem != nOrigSystem )
	{
		switch (nNewSystem) {
			case 1:
				default_system = 1;		// OS-A
				break;
			case 2:
				default_system = 2;		// OS-B
				break;
			case 3:
				default_system = 3;		// 800 XL
				break;
			case 4:
				default_system = 4;		// 130 XE
				break;
			case 5:
				default_system = 5;
				Ram256 = 2;
				ulMiscStates &= ~ATARI_RAMBO_MODE;
				break;
			case 6:
				default_system = 5;
				Ram256 = 1;
				ulMiscStates |= ATARI_RAMBO_MODE;
				break;
			case 7:
				default_system = 6;
				break;
			default:
				default_system = 2;		// OS-B
				break;
		}

		bReboot = TRUE;
		WriteRegDWORD( NULL, REG_DEFAULT_SYSTEM, default_system );
	}

	if( ulTempStates != ulMiscStates )
		WriteRegDWORD( NULL, REG_MISC_STATES, ulMiscStates);


	if( ntemp_refresh_rate != refresh_rate )
	{
		refresh_rate = ntemp_refresh_rate;
		WriteRegDWORD( NULL, REG_REFRESH_RATE, ntemp_refresh_rate);
	}

	if( ntemp_tv_mode != default_tv_mode )
	{
		default_tv_mode = ntemp_tv_mode;
		bReboot = TRUE;
		WriteRegDWORD( NULL, REG_DEFAULT_TV_MODE, ntemp_tv_mode);
	}

	//If the atari load failed, we just reset hWnd to NULL and the Atari will
	//be rebooted when the screen is refreshed in OnDraw
	if( bReboot )
	{
		Atari_ReInit();
	}
	CDialog::OnOK();
}


